Classes
The following classes are available globally.
-
See moreKeychainStorageis a generic class that conforms to theStorageDelegateprotocol, providing a secure storage solution by leveraging the keychain. It is designed to store, retrieve, and manage objects of typeT, whereTmust conform to theCodableprotocol. This requirement ensures that the objects can be easily encoded and decoded for secure storage in the keychain.Declaration
Swift
public class KeychainStorage<T> : StorageDelegate<T>, @unchecked Sendable where T : Decodable, T : Encodable, T : SendableParameters
TThe type of the objects to be stored in the keychain. Must conform to
Codable. -
MemoryStorageprovides an in-memory storage solution with optional caching strategies.This class combines the simplicity of in-memory storage with the flexibility of caching strategies. It’s built on top of
StorageDelegateand uses theMemory<T>actor for the underlying storage.Overview
MemoryStorageis ideal for temporary data that doesn’t need to persist across app launches. Since the underlying storage is already in memory, the caching layer adds an additional level of indirection that can be useful for specific scenarios.When to Use Memory Storage
- Temporary session data: User session information that’s cleared on logout
- In-flight data: Data being processed that doesn’t need persistence
- Performance testing: Testing storage patterns without disk I/O overhead
- Cached computations: Results that can be recomputed if needed
Caching with Memory Storage
While it may seem redundant to cache in-memory storage, the caching layer can be useful for:
Testing Cache Behavior
// Test how your app handles cache strategies let storage = MemoryStorage<Config>(cacheStrategy: .CACHE_ON_FAILURE) // Simulate failures and verify fallback behaviorConsistent API
// Use the same caching API across all storage types let memStorage = MemoryStorage<Token>(cacheStrategy: .CACHE) let keychainStorage = KeychainStorage<Token>(cacheStrategy: .CACHE) // Both support the same operations and strategiesPerformance Benchmarking
let noCacheStorage = MemoryStorage<Data>(cacheStrategy: .NO_CACHE) let cachedStorage = MemoryStorage<Data>(cacheStrategy: .CACHE) // Compare performance characteristicsTypical Usage
For most use cases with
MemoryStorage, use.NO_CACHE(the default) since the underlying storage is already in memory:// Default: no additional cache layer (recommended) let sessionData = MemoryStorage<Session>() try await sessionData.save(item: currentSession)Migration from Legacy API
The
cacheableparameter is removed. UsecacheStrategyinstead:Before:
let storage = MemoryStorage<User>(cacheable: true)After:
let storage = MemoryStorage<User>(cacheStrategy: .CACHE)Thread Safety
All operations are thread-safe through Swift actor isolation. Concurrent access from multiple tasks is handled safely without external synchronization.
Important
Data stored in
MemoryStorageis lost when the app terminates. UseKeychainStorageor other persistent storage for data that must survive app restarts.See moreSee also
Declaration
Swift
public class MemoryStorage<T> : StorageDelegate<T>, @unchecked Sendable where T : Decodable, T : Encodable, T : SendableParameters
TThe type of the objects to be stored. Must conform to
Codablefor serialization andSendablefor safe concurrent access. -
A storage delegate class that provides flexible caching strategies for storage operations.
StorageDelegateacts as a wrapper around anyStorageimplementation, adding an optional in-memory caching layer. This enables various performance and resilience patterns depending on your application’s requirements.Overview
The delegate pattern allows you to:
- Add caching to any storage implementation without modifying the underlying storage
- Choose from multiple caching strategies to match your use case
- Maintain thread-safe concurrent access through Swift actors
- Provide degraded functionality during storage failures
Caching Strategies
Three caching strategies are available through the
CacheStrategyenum:NO_CACHE (Default)
All operations go directly to the underlying storage with no caching layer.
let storage = StorageDelegate( delegate: KeychainStorage(), cacheStrategy: .NO_CACHE )Use when: You always need fresh data and memory usage is a concern.
CACHE
Items are cached in memory on save. Reads are served from cache when available.
let storage = StorageDelegate( delegate: RemoteStorage(), cacheStrategy: .CACHE )Use when: Performance is critical and you can tolerate cache-storage inconsistencies on failures.
CACHE_ON_FAILURE
Items are cached after successful operations. Cache serves as fallback during storage failures.
let storage = StorageDelegate( delegate: NetworkStorage(), cacheStrategy: .CACHE_ON_FAILURE )Use when: You need resilience against intermittent failures and can tolerate stale data.
Thread Safety
All caching operations are thread-safe through the use of Swift actors. Multiple concurrent reads and writes are handled safely without the need for external synchronization.
Example Usage
// High-performance cached configuration let config = StorageDelegate( delegate: KeychainStorage(account: "app.config"), cacheStrategy: .CACHE ) try await config.save(item: appConfig) let cachedConfig = try await config.get() // Served from cache // Resilient network storage let userData = StorageDelegate( delegate: NetworkKeychain(account: "user.data"), cacheStrategy: .CACHE_ON_FAILURE ) try await userData.save(item: user) // Later, even if network fails... let user = try await userData.get() // Falls back to cacheNote
This class is designed to be subclassed by specific storage strategies (e.g.,
MemoryStorage,KeychainStorage) that conform to theStorageprotocol.See moreSee also
Declaration
Swift
open class StorageDelegate<T> : Storage, @unchecked Sendable where T : Decodable, T : Encodable, T : SendableParameters
TThe type of the object being stored. Must conform to
CodableandSendableto ensure safe encoding/decoding and concurrent access.
View on GitHub
Classes Reference