ModernSwiftStorage
ModernSwiftStorage is a comprehensive, type-safe storage solution for iOS, macOS, watchOS, and tvOS applications. It provides seamless integration between UserDefaults and Keychain with automatic security routing, SwiftUI property wrappers, and built-in analytics.
Why ModernSwiftStorage?
Traditional iOS storage solutions often require:
- Manual decision-making between UserDefaults and Keychain
- Boilerplate code for encoding/decoding
- Separate implementations for different data types
- Manual security considerations
ModernSwiftStorage solves these problems by providing:
✅ Automatic Security Routing - Sensitive data automatically goes to Keychain
✅ Type Safety - Generic methods with compile-time checking
✅ SwiftUI Integration - Native property wrappers
✅ Cross-Platform Support - Works on all Apple platforms
✅ Built-in Analytics - Automatic usage statistics
✅ Easy Testing - Protocol-based design with mock support
Installation
Add ModernSwiftStorage to your project using Swift Package Manager:
dependencies: [ .package(url: "https://github.com/Maxnxi/ModernSwiftStorage.git", from: "1.0.0") ] Quick Start
1. Basic App Setup
import SwiftUI import ModernSwiftStorage @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() .withSimpleStorageService() } } } 2. Property Wrapper Usage
The most convenient way to use ModernSwiftStorage is through property wrappers:
struct SettingsView: View { @Storage("user.name") private var userName = "Guest" @Storage("notifications.enabled") private var notificationsEnabled = true @Storage("theme.isDark") private var isDarkTheme = false // Sensitive data automatically routed to Keychain @SecureStorage("auth.token") private var authToken = "" @SecureStorage("user.password") private var password = "" var body: some View { Form { TextField("Name", text: $userName) Toggle("Notifications", isOn: $notificationsEnabled) Toggle("Dark Theme", isOn: $isDarkTheme) SecureField("Auth Token", text: $authToken) } } } Storage Types and Automatic Security
Automatic Storage Selection (Recommended)
ModernSwiftStorage automatically determines the appropriate storage based on the key name:
@Storage("user.name") private var userName = "Guest" // → UserDefaults @Storage("auth.token") private var token = "" // → Keychain (auto-detected) @Storage("user.password") private var password = "" // → Keychain (auto-detected) @Storage("api.secret") private var apiSecret = "" // → Keychain (auto-detected) Sensitive Keywords that trigger automatic Keychain storage:
password-
token secretkeycredentialauth
Explicit Storage Types
You can also explicitly specify the storage type:
@UserDefaultsStorage("app.version") private var version = "1.0" @SecureStorage("biometric.data") private var biometricData = "" // Manual specification @Storage("data", storageType: .userDefaults) private var data = "" @Storage("secret", storageType: .keychain()) private var secret = "" Keychain Accessibility Options
Control when Keychain data is accessible:
@Storage("token", storageType: .keychain(accessibility: .whenUnlocked)) private var token = "" @Storage("biometric", storageType: .keychain(accessibility: .whenPasscodeSetThisDeviceOnly)) private var biometric = "" Available accessibility options:
-
.whenUnlocked- Default, accessible when device is unlocked -
.afterFirstUnlock- Accessible after first unlock since boot -
.whenPasscodeSetThisDeviceOnly- Requires passcode, device-specific -
.whenUnlockedThisDeviceOnly- Device-specific, when unlocked
Type-Safe Storage Keys
For better organization and type safety, define custom storage keys:
extension ModernStorage.Keys { struct UserProfile: StorageKey { typealias Value = UserProfileModel let key = "user.profile.v2" let defaultValue = UserProfileModel() let storageType = StorageType.userDefaults } struct APICredentials: StorageKey { typealias Value = APICredentialsModel let key = "api.credentials" let defaultValue = APICredentialsModel() let isSensitive = true // Automatically uses Keychain } } // Usage struct MyView: View { @Storage(ModernStorage.Keys.UserProfile()) private var profile @Storage(ModernStorage.Keys.APICredentials()) private var credentials var body: some View { VStack { TextField("Name", text: $profile.fullName) SecureField("API Key", text: $credentials.apiKey) } } } Direct Storage Service Access
Access the storage service directly for programmatic operations:
struct DataManager { @Environment(\.simpleStorageService) private var storage func saveUserData(_ data: UserData) { storage.set(data, forKey: "user.data") } func loadUserData() -> UserData { return storage.get(key: "user.data", defaultValue: UserData()) } func clearSensitiveData() { storage.remove(key: "auth.token", storageType: .keychain()) } func bulkUpdate() { storage.setBool(true, forKey: "feature.enabled") storage.setInt(42, forKey: "user.score") storage.setString("premium", forKey: "subscription.tier") } } Working with Complex Data Types
Any Codable type is automatically supported:
struct UserProfile: Codable { var name: String var email: String var preferences: [String: String] var lastLogin: Date var settings: UserSettings } struct UserSettings: Codable { var theme: String var language: String var notifications: Bool } // Usage @Storage("user.profile") private var profile = UserProfile( name: "", email: "", preferences: [:], lastLogin: Date(), settings: UserSettings(theme: "system", language: "en", notifications: true) ) Built-in Analytics and Statistics
ModernSwiftStorage automatically tracks app usage without additional setup:
struct StatisticsView: View { @Environment(\.simpleStorageService) private var storage var body: some View { VStack(alignment: .leading, spacing: 12) { Text("Days using app: \(storage.statistics.statistics.daysUsingApp)") Text("Total app opens: \(storage.statistics.statistics.timesUsingApp)") Text("Today's sessions: \(storage.statistics.statistics.timesDailyUsingApp)") Text("App installs: \(storage.statistics.statistics.timesAppInstalled)") Button("Update Statistics") { storage.statistics.updateStatistics() } Button("Reset Statistics") { storage.statistics.resetStatistics() } } } } Data Migration
Migrate data between storage types when needed:
let migrationManager = StorageMigrationManager() // Migrate sensitive data from UserDefaults to Keychain await migrationManager.migrateFromUserDefaultsToKeychain( key: "old.token", accessibility: .whenUnlocked ) // Migrate data from Keychain to UserDefaults (if needed) await migrationManager.migrateFromKeychainToUserDefaults( key: "non.sensitive.data" ) Testing and Mocking
ModernSwiftStorage is designed with testing in mind:
#if DEBUG struct TestView: View { var body: some View { MyView() .withSimpleStorageService( userDefaultsManager: MockUserDefaultsManager(), keychainManager: MockKeychainManager() ) } } #endif // Unit Testing class MyViewModelTests: XCTestCase { var storage: ModernStorage! override func setUp() { storage = ModernStorage( userDefaultsManager: MockUserDefaultsManager(), keychainManager: MockKeychainManager() ) } func testDataPersistence() { storage.set("test", forKey: "key") XCTAssertEqual(storage.get(key: "key", defaultValue: ""), "test") } } Advanced Configuration
Customize ModernSwiftStorage for specific needs:
let config = StorageConfiguration( serviceName: "com.myapp.storage", userDefaultsSuiteName: "group.myapp.shared", defaultKeychainAccessibility: .afterFirstUnlock, enableStatistics: true, enableMigration: true ) let customStorage = SimpleStorageService(configuration: config) // Use in your app struct MyApp: App { var body: some Scene { WindowGroup { ContentView() .withSimpleStorageService(customStorage) } } } Error Handling and Validation
Validate storage operations and handle errors:
do { // Validate key before use guard StorageValidator.validateKey("my.key") else { throw StorageError.invalidKey("my.key") } // Validate storage type appropriateness guard StorageValidator.validateStorageType(SensitiveData.self, storageType: .userDefaults) else { throw StorageError.unsupportedType } storage.set(data, forKey: "my.key") } catch { print("Storage error: \(error.localizedDescription)") } Best Practices
1. Use Automatic Storage Selection
Let ModernSwiftStorage decide the appropriate storage type:
// Good - automatic selection @Storage("user.preferences") private var preferences = UserPreferences() @Storage("auth.token") private var token = "" // Only specify explicitly when needed @Storage("temp.data", storageType: .userDefaults) private var tempData = "" 2. Define Storage Keys for Type Safety
extension ModernStorage.Keys { struct AppSettings: StorageKey { typealias Value = AppSettingsModel let key = "app.settings.v2" let defaultValue = AppSettingsModel() let storageType = StorageType.userDefaults } } 3. Use Descriptive Key Names
// Good @Storage("user.profile.display.name") private var displayName = "" @Storage("auth.session.token") private var sessionToken = "" // Avoid @Storage("name") private var displayName = "" @Storage("token") private var sessionToken = "" 4. Group Related Settings
struct NotificationSettings: Codable { var pushEnabled: Bool = true var emailEnabled: Bool = false var frequency: String = "daily" } @Storage("notifications.settings") private var notificationSettings = NotificationSettings() Platform Support and Requirements
- iOS 13.0+
- macOS 10.15+
- watchOS 6.0+
- tvOS 13.0+
Thread Safety
All storage operations are marked with @MainActor for thread safety in SwiftUI contexts. For background operations:
Task { @MainActor in storage.set(data, forKey: "background.key") } Performance Considerations
- UserDefaults operations are synchronous and fast for small data
- Keychain operations have slightly more overhead but remain performant
- Complex objects are automatically JSON encoded/decoded
- Statistics tracking has minimal performance impact
- Bulk operations are optimized internally
Conclusion
ModernSwiftStorage
https://github.com/Maxnxi/ModernSwiftStorage.git
provides a powerful, type-safe, and secure storage solution that eliminates the complexity of managing UserDefaults and Keychain manually. With its automatic security routing, SwiftUI integration, and built-in analytics, it's the perfect storage solution for modern iOS applications.
Whether you're building a simple settings screen or a complex app with sensitive data, ModernSwiftStorage adapts to your needs while maintaining security best practices automatically.

Top comments (0)