2.6 KiB
2.6 KiB
LocalData Migration Guide
Overview
LocalData provides protocol-based migration support to move data from legacy storage locations to modern StorageKey values.
Automatic Migration
When calling get(_:) on a key, the StorageRouter automatically:
- Checks the primary location.
- If not found, evaluates
migrationdefined on the key. - If data is found in a source:
- Unsecures it using the source's old policy.
- Re-secures it using the destination key's policy.
- Stores it in the new location.
- Deletes the legacy data.
- Returns the value.
Proactive Migration (Sweep)
You can trigger a sweep of all registered keys at app launch:
try await StorageRouter.shared.registerCatalog(MyCatalog(), migrateImmediately: true)
This iterates through all keys in the catalog and calls forceMigration(for:) on each, ensuring all legacy data is consolidated.
Defining Migration Sources
Simple Legacy Migration
For 1:1 migrations, attach a SimpleLegacyMigration:
extension StorageKey where Value == String {
static let legacyToken = StorageKey(
name: "old_key_name",
domain: .userDefaults(suite: nil),
security: .none,
serializer: .json,
owner: "MigrationDemo",
description: "Legacy token stored in UserDefaults."
)
static let modernToken = StorageKey(
name: "modern_token",
domain: .keychain(service: "com.myapp"),
owner: "MigrationDemo",
description: "Modern token stored in Keychain.",
migration: { key in
AnyStorageMigration(
SimpleLegacyMigration(
destinationKey: key,
sourceKey: .key(StorageKey.legacyToken)
)
)
}
)
}
Protocol-Based Migration
For complex scenarios, attach an explicit migration:
struct MyMigration: StorageMigration {
typealias Value = String
let destinationKey = StorageKey.modernToken
func shouldMigrate(using router: StorageRouter, context: MigrationContext) async throws -> Bool {
try await router.exists(destinationKey)
}
func migrate(using router: StorageRouter, context: MigrationContext) async throws -> MigrationResult {
// Custom migration logic
MigrationResult(success: true)
}
}
extension StorageKey where Value == String {
static let modernToken = StorageKey(
name: "modern_token",
domain: .keychain(service: "com.myapp"),
owner: "MigrationDemo",
description: "Modern token stored in Keychain.",
migration: { _ in AnyStorageMigration(MyMigration()) }
)
}