Skip to content

Repository files navigation

English | 日本語

SwiftPersistence

Read and write app data through one protocol, whichever store it lands in — so a use case can be tested without UserDefaults, the Keychain, or the disk.

Swift Platforms License

Your domain and use-case layers depend on a protocol; the composition root picks whether that protocol is backed by UserDefaults, the Keychain, the file system, or nothing at all.

Features

  • Protocol-oriented — every storage operation is an abstract protocol, so a use case can be tested without touching disk, the Keychain, or an entitlement
  • KeyValueStore — a type-safe UserDefaults abstraction; primitives go through native accessors and any other Codable type is JSON-encoded automatically
  • SecureStore — a Keychain wrapper for API keys and credentials, with an explicit accessibility policy that defaults to this-device-only
  • DocumentStore — file-backed CRUD, one JSON file per document, written atomically
  • RegistryStore — a whole [String: Codable] dictionary in a single JSON file, for caches and metadata indexes
  • KeyResolver — multi-source fallback in a fixed order: Info.plist, then Keychain, then UserDefaults
  • In-memory doubles for every protocol — seedable, actor-isolated, and shipped in their own module so they never reach a production target

Quick Start

import PersistenceUserDefaults

let store = UserDefaultsKeyValueStore()

try await store.setValue("dark", forKey: "theme")
let theme: String? = try await store.string(forKey: "theme")

Depend on the protocol, not the backend, and the same code runs against the real store in the app and against an in-memory double in tests:

import PersistenceCore
import PersistenceTesting

let store: any KeyValueStore = InMemoryKeyValueStore(["theme": "dark"])

Documentation

API reference and guides — including Getting Started and Architecture, which explains what each backend guarantees about durability, threading, and decode failure.

Installation

// Package.swift
dependencies: [
    .package(url: "https://github.com/no-problem-dev/swift-persistence.git", from: "3.0.0")
]

Add only the modules a target actually needs:

.product(name: "PersistenceCore",         package: "swift-persistence"),
.product(name: "PersistenceUserDefaults", package: "swift-persistence"),
.product(name: "PersistenceKeychain",     package: "swift-persistence"),
.product(name: "PersistenceFileSystem",   package: "swift-persistence"),
.product(name: "PersistenceTesting",      package: "swift-persistence"),  // test targets only

Requirements

  • iOS 17.0+ / macOS 14.0+
  • Linux — every module except PersistenceKeychain, which needs Apple's Security framework. Conform your own type to SecureStore there.
  • Swift 6.2+
  • Xcode 16.0+

License

MIT — see LICENSE.

About

Read and write app data through one protocol, whichever store it lands in — so a use case can be tested without UserDefaults, the Keychain, or the disk

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages