Getting Started
ForgeStorage provides three protocol-driven stores for iOS: key-value storage, file storage, and Keychain storage. All are type-safe, testable, and designed for Swift concurrency.
Requirements
- iOS 18+ / macOS 15+
- Swift 6.3+
- Xcode 26+
Installation
Xcode
- Open your project in Xcode.
- Go to File → Add Package Dependencies.
- Enter the repository URL:
https://github.com/stefanprojchev/ForgeStorage - Set the version rule to Up to Next Major from
1.0.0. - Add
ForgeStorageto your target.
Package.swift
Add ForgeStorage as a dependency in your Package.swift:
dependencies: [
.package(url: "https://github.com/stefanprojchev/ForgeStorage", from: "1.0.0")
] Then add the modules you need to your target. Use ForgeStorage for everything, or pick individual modules:
targets: [
.target(
name: "TaskFlow",
dependencies: [
"ForgeStorage", // all three modules
// — or pick individually —
// "ForgeKVStore", // key-value storage only
// "ForgeFileStore", // file storage only
// "ForgeCrypt", // keychain storage only
]
)
] Swift CLI
swift package add-dependency https://github.com/stefanprojchev/ForgeStorage --from 1.0.0 The Three Modules
ForgeStorage ships four libraries. Three standalone modules plus an umbrella that re-exports all of them:
| Module | Protocol | Production | Test | Purpose |
|---|---|---|---|---|
ForgeKVStore | KVStoring | UserDefaultsKVStore, DiskKVStore | InMemoryKVStore | Settings, flags, small data |
ForgeFileStore | FileStoring | DiskFileStore | InMemoryFileStore | Images, videos, documents, cache |
ForgeCrypt | CryptStoring | CryptStore | InMemoryCrypt | Tokens, passwords, secrets |
import ForgeStorage gives you everything. Or import only what you need:
import ForgeKVStore // just key-value
import ForgeFileStore // just file storage
import ForgeCrypt // just keychain
import ForgeStorage // all three Quick Examples
Key-Value Storage
Define type-safe keys, then read and write through the KVStoring protocol. get() returns nil when no value is set.
import ForgeKVStore
// Define type-safe keys
enum TaskFlowKeys {
static let onboarding = KVKey<Bool>("taskflow.onboarding")
static let username = KVKey<String?>("taskflow.username")
static let launchCount = KVKey<Int>("taskflow.launchCount")
}
// Use any KVStoring implementation
let store: KVStoring = UserDefaultsKVStore()
try store.set(TaskFlowKeys.onboarding, value: true)
let done = store.get(TaskFlowKeys.onboarding) ?? false // true
let count = store.get(TaskFlowKeys.launchCount) ?? 0
try store.set(TaskFlowKeys.launchCount, value: count + 1) File Storage
Save, load, and manage binary files in sandboxed directories.
import ForgeFileStore
let store = DiskFileStore(directory: .caches, namespace: "taskflow-attachments")
// Save data
let attachmentData = Data(/* ... */)
try await store.save(attachmentData, to: "tasks/task_42/photo.jpg")
// Load data
let data = try await store.load("tasks/task_42/photo.jpg")
// Check existence
if store.exists("tasks/task_42/photo.jpg") {
let info = try store.info(for: "tasks/task_42/photo.jpg")
print("Size: \(info.size) bytes")
}
// Clean up
try await store.deleteAll() Keychain Storage
Store secrets with hardware-backed encryption. No default values — missing items return nil.
import ForgeCrypt
// Define keys with accessibility levels
enum AuthKeys {
static let accessToken = CryptKey<String>(
key: "auth.accessToken",
accessibility: .afterFirstUnlock
)
static let refreshToken = CryptKey<String>(
key: "auth.refreshToken",
accessibility: .afterFirstUnlock
)
}
let keychain: CryptStoring = CryptStore(service: "com.taskflow")
// Store
try keychain.set("eyJhbG...", for: AuthKeys.accessToken)
// Retrieve (returns nil if not set)
let token: String? = try keychain.get(AuthKeys.accessToken)
// Delete
try keychain.delete(AuthKeys.accessToken) Next Steps
- Dive into ForgeKVStore for the full key-value API and observation support.
- Learn about ForgeFileStore for managing binary files.
- See ForgeCrypt for secure credential management.
- Set up Testing with in-memory implementations.