Type-safe key-value, file, and Keychain storage for iOS.
ForgeStorage covers every persistence need in a typical iOS app through three focused libraries. Each library exposes a protocol, a production implementation, and an in-memory test double β so you can swap the storage layer out for tests without touching your production code.
| Library | Protocol | Production | Test double | Use for |
|---|---|---|---|---|
| ForgeKVStore | KVStoring |
UserDefaultsKVStore, DiskKVStore |
InMemoryKVStore |
Settings, flags, small data |
| ForgeFileStore | FileStoring |
DiskFileStore |
InMemoryFileStore |
Images, videos, documents, cache |
| ForgeCrypt | CryptStoring |
CryptStore (Keychain) |
InMemoryCrypt |
Tokens, passwords, secrets |
| ForgeStorage | umbrella | β | β | Re-exports all three |
- Type-safe keys β
KVKey<T>andCryptKey<T>give compile-time safety for reads and writes - Protocol-oriented β every store is behind a protocol, making mocking trivial
- Reactive KV β wrap any
KVStoringwithKVReactiveStoreforAsyncStream-based observation - Configurable Keychain accessibility β
.whenUnlocked,.afterFirstUnlock,.whenUnlockedThisDeviceOnly, etc. - JSON convenience β built-in Codable round-trips for file and KV stores
- Zero Combine dependency β pure Swift Concurrency
- iOS 18+
- macOS 15+
- Swift 6.3+ (Xcode 26 or later)
- File β Add Package Dependenciesβ¦
- Paste
https://github.com/stefanprojchev/ForgeStorage.git - Set rule to Up to Next Major from
1.0.0
dependencies: [
.package(url: "https://github.com/stefanprojchev/ForgeStorage.git", from: "1.0.0")
],
targets: [
.target(
name: "YourApp",
dependencies: [
"ForgeStorage", // all three libraries
// β or pick individually β
// "ForgeKVStore",
// "ForgeFileStore",
// "ForgeCrypt",
]
)
]import ForgeKVStore
// Define typed keys
enum AppKeys {
static let onboarded = KVKey<Bool>("app.onboarded")
static let launchCount = KVKey<Int>("app.launchCount")
}
let store: KVStoring = UserDefaultsKVStore()
try store.set(AppKeys.onboarded, value: true)
let done = store.get(AppKeys.onboarded) ?? falseimport ForgeKVStore
let reactive = KVReactiveStore(UserDefaultsKVStore())
for await value in reactive.stream(AppKeys.launchCount) {
print("Launch count:", value ?? 0)
}import ForgeFileStore
let store = DiskFileStore(directory: .caches, namespace: "avatars")
try await store.save(imageData, to: "user_42.jpg")
let data = try await store.load("user_42.jpg")
// JSON convenience
try await store.saveJSON(user, to: "user.json")
let loaded: User = try await store.loadJSON("user.json")import ForgeCrypt
enum AuthKeys {
static let accessToken = CryptKey<String>(
key: "auth.accessToken",
accessibility: .afterFirstUnlock
)
}
let keychain: CryptStoring = CryptStore(service: "com.yourapp")
try keychain.set("eyJhbG...", for: AuthKeys.accessToken)
let token: String? = try keychain.get(AuthKeys.accessToken)
try keychain.delete(AuthKeys.accessToken)Every store has an in-memory test double you can use instead of the production implementation:
import Testing
import ForgeKVStore
@Test
func incrementsLaunchCount() throws {
let store: KVStoring = InMemoryKVStore()
let initial = store.get(AppKeys.launchCount) ?? 0
try store.set(AppKeys.launchCount, value: initial + 1)
#expect(store.get(AppKeys.launchCount) == 1)
}- Getting Started
- ForgeKVStore β key-value API, reactive streams, property wrapper
- ForgeFileStore β binary file storage and JSON convenience
- ForgeCrypt β Keychain storage with accessibility levels
- Testing
ForgeStorage is part of the Forge family of Swift packages for iOS.
| Package | Description |
|---|---|
| ForgeCore | Thread-safe primitives for iOS Swift packages. |
| ForgeInject | Dependency injection with constructor and property wrapper support. |
| ForgeObservers | Reactive system observers β connectivity, lifecycle, keyboard, and more. |
| ForgeStorage | Type-safe key-value, file, and Keychain storage. |
| ForgeOrchestrator | Orchestrate app flows β startup gates, data pipelines, and continuous monitors. |
| ForgePush | Push notification management β permissions, tokens, and routing. |
| ForgeLocation | Location triggers β geofencing, significant changes, and visits. |
| ForgeBackgroundTasks | Background task scheduling and dispatch. |
ForgeStorage is released under the MIT License. See LICENSE.