English | 日本語
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.
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.
- 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
UserDefaultsabstraction; primitives go through native accessors and any otherCodabletype 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, thenUserDefaults - In-memory doubles for every protocol — seedable, actor-isolated, and shipped in their own module so they never reach a production target
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"])API reference and guides — including Getting Started and Architecture, which explains what each backend guarantees about durability, threading, and decode failure.
// 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- iOS 17.0+ / macOS 14.0+
- Linux — every module except
PersistenceKeychain, which needs Apple's Security framework. Conform your own type toSecureStorethere. - Swift 6.2+
- Xcode 16.0+
MIT — see LICENSE.