### Example usage of ObservableDefaults and ObservableCloud initialization in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Shows practical examples of initializing both UserDefaults-backed and cloud-backed settings with custom parameters. Demonstrates how to configure prefix, ignore external changes, and control synchronization behavior. ```swift // UserDefaults-backed settings @State var settings = Settings( userDefaults: .standard, ignoreExternalChanges: false, prefix: "myApp_" ) // Cloud-backed settings @State var cloudSettings = CloudSettings( prefix: "myApp_", syncImmediately: true, developmentMode: false ) ``` -------------------------------- ### Swift Initialization Patterns for ObservableDefaults Source: https://github.com/fatbobman/observabledefaults/blob/main/AI_REFERENCE.md Demonstrates two initialization patterns for classes using the @ObservableDefaults macro: auto-generated initializers (default) and custom initializers that require manual observer setup. ```swift // Auto-generated initializer (autoInit: true - default) @ObservableDefaults class Settings { var name: String = "default" } // Custom initializer (autoInit: false) @ObservableDefaults(autoInit: false) class Settings { var name: String = "default" init() { observerStarter() // Must call for external change observation } } ``` -------------------------------- ### Swift: Development Mode for Testing with ObservableCloud Source: https://github.com/fatbobman/observabledefaults/blob/main/AI_REFERENCE.md Shows how to use the development mode for ObservableCloud, which facilitates testing and previews by using in-memory storage instead of actual cloud synchronization. This allows for easy setup and tear down of settings during development. ```swift @ObservableCloud(developmentMode: true) class TestCloudSettings { var setting1: String = "test" var setting2: Int = 42 } // In tests or previews let testSettings = TestCloudSettings() // Uses memory storage ``` -------------------------------- ### Swift: Observe First Mode Example with ObservableDefaults Source: https://github.com/fatbobman/observabledefaults/blob/main/AI_REFERENCE.md Illustrates the 'observe first' mode in ObservableDefaults, allowing for explicit control over which properties are observable, backed by UserDefaults, or observable only. The example defines a class with properties marked with @ObservableDefaults, @DefaultsBacked, @ObservableOnly, and @Ignore. ```swift @ObservableDefaults(observeFirst: true) class MixedSettings { var tempSelection: Int = 0 // Observable only @DefaultsBacked var persistentSetting: String = "" // UserDefaults backed @ObservableOnly var computedValue: String = "" // Observable only (explicit) @Ignore var internalState: Bool = false // Neither observable nor persistent } ``` -------------------------------- ### Create custom initializer when autoInit is disabled in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Shows how to implement custom initializers when autoInit parameter is set to false for either @ObservableDefaults or @ObservableCloud macros. Required to manually start observation mechanisms. ```swift // For @ObservableDefaults init() { observerStarter() // Start listening for UserDefaults changes } // For @ObservableCloud init() { // Start Cloud Observation only in production mode if !_developmentMode_ { _cloudObserver = CloudObservation(host: self, prefix: _prefix) } } ``` -------------------------------- ### Optional Type Support with UserDefaults and iCloud in Swift Source: https://context7.com/fatbobman/observabledefaults/llms.txt Illustrates handling optional properties with automatic nil handling for UserDefaults using @ObservableDefaults and iCloud using @ObservableCloud. Includes examples for various optional types and usage in SwiftUI views with nil checks. ```swift import ObservableDefaults // UserDefaults with optionals @ObservableDefaults class OptionalSettings { var username: String? = nil // No value initially var lastLoginDate: Date? = nil var age: Int? = 25 // Has initial value var preferences: [String]? = nil @DefaultsKey(userDefaultsKey: "custom_optional") var customOptional: String? = nil } // iCloud with optionals @ObservableCloud class CloudOptionalSettings { var cloudUsername: String? = nil var syncedData: [String: String]? = nil var lastSyncTime: Date? = nil } // Usage example with proper nil handling struct OptionalSettingsView: View { @State private var settings = OptionalSettings() var body: some View { Form { Section("Optional Values") { if let username = settings.username { Text("Username: \(username)") Button("Clear Username") { settings.username = nil } } else { Button("Set Username") { settings.username = "NewUser" } } if let lastLogin = settings.lastLoginDate { Text("Last login: \(lastLogin.formatted())") } else { Text("Never logged in") Button("Set Login Time") { settings.lastLoginDate = Date() } } } } } } ``` -------------------------------- ### Customizing Behavior with Additional Macros for @ObservableDefaults Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Provides examples of additional macros for finer control over @ObservableDefaults properties, including custom UserDefaults keys and observable-only properties. ```swift @ObservableDefaults public class LocalSettings { @DefaultsKey(userDefaultsKey: "firstName") public var name: String = "fat" public var age = 109 // Automatically backed by UserDefaults @ObservableOnly public var height = 190 // Observable only, not persisted @Ignore public var weight = 10 // Neither observable nor persisted } ``` -------------------------------- ### Implement custom types with Codable for Cloud Storage in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Example of implementing custom types with Codable protocol for use with @ObservableCloud macro and cloud storage. Complex nested structures are supported as long as all components conform to Codable. ```swift @ObservableCloud class CloudStore { var userProfile: UserProfile = .init(name: "fat", preferences: .init()) } struct UserProfile: Codable { var name: String var preferences: UserPreferences } struct UserPreferences: Codable { var theme: String = "light" var fontSize: Int = 14 } ``` -------------------------------- ### Enum RawRepresentable Types in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Shows how enums with RawValue conforming to property-list set are persisted automatically. Includes an example of Theme enum and its usage in an ObservableDefaults class. ```swift enum Theme: String { case light case dark case system } @ObservableDefaults class AppearanceSettings { var theme: Theme = Theme.system } ``` -------------------------------- ### Use Observe First for Mixed Settings in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md This Swift example shows using observeFirst parameter in ObservableDefaults for classes with mixed persisted and non-persisted properties. It separates UI state from important settings. Requires ObservableDefaults framework; inputs are property values, outputs are observed changes with correct persistence; ensure important settings are marked appropriately to prevent data loss. ```swift @ObservableDefaults(observeFirst: true) class MixedSettings { // Temporary UI state (not persisted) var currentTab: Int = 0 var searchText: String = "" // Important settings (persisted) @DefaultsBacked var username: String = "" @DefaultsBacked var isFirstLaunch: Bool = true } ``` -------------------------------- ### Enum and RawRepresentable Support with UserDefaults and iCloud in Swift Source: https://context7.com/fatbobman/observabledefaults/llms.txt Demonstrates storing enums using their raw values with @ObservableDefaults for UserDefaults and @ObservableCloud for iCloud. Supports enums with String and Int raw values, and includes usage examples in SwiftUI views. ```swift import ObservableDefaults // Enums with String raw values enum Theme: String, Codable { case light case dark case system } enum FontStyle: Int, Codable { case regular = 0 case bold = 1 case italic = 2 } // UserDefaults with enums @ObservableDefaults class EnumSettings { var theme: Theme = .system // Stored as "system" string var fontStyle: FontStyle = .regular // Stored as 0 integer var quality: VideoQuality = .high } enum VideoQuality: String, Codable { case low, medium, high, ultra } // iCloud with enums @ObservableCloud class CloudEnumSettings { var preferredTheme: Theme = .light var textStyle: FontStyle = .regular } // Usage example struct ThemePickerView: View { @State private var settings = EnumSettings() var body: some View { Form { Picker("Theme", selection: $settings.theme) { Text("Light").tag(Theme.light) Text("Dark").tag(Theme.dark) Text("System").tag(Theme.system) } Picker("Font Style", selection: $settings.fontStyle) { Text("Regular").tag(FontStyle.regular) Text("Bold").tag(FontStyle.bold) Text("Italic").tag(FontStyle.italic) } } } } ``` -------------------------------- ### Integrate ObservableDefaults with View State Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md This Swift snippet demonstrates how to integrate ObservableDefaults-backed settings into an Observable ViewState class for a SwiftUI app. It manages local and cloud settings separately from main state, using UserDefaults and iCloud. The example shows UI interactions that modify persisted data, with dependencies on SwiftUI and Combine frameworks; inputs are button actions, outputs are updated text views; limitations include potential iCloud sync delays. ```swift @Observable class ViewState { var selection = 10 var isLogin = false let localSettings = LocalSettings() // UserDefaults-backed let cloudSettings = CloudSettings() // iCloud-backed } struct ContentView: View { @State var state = ViewState() var body: some View { VStack(spacing: 30) { // Local settings Text("Local Name: \(state.localSettings.name)") Button("Modify Local Setting") { state.localSettings.name = "User \(Int.random(in: 0...1000))" } // Cloud settings Text("Cloud Username: \(state.cloudSettings.username)") Button("Modify Cloud Setting") { state.cloudSettings.username = "CloudUser \(Int.random(in: 0...1000))" } } .buttonStyle(.bordered) } } ``` -------------------------------- ### Implement custom types with Codable for UserDefaults in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Example of implementing custom types with Codable protocol for use with @ObservableDefaults macro and UserDefaults storage. The custom struct must conform to Codable to be properly serialized. ```swift @ObservableDefaults class LocalStore { var people: People = .init(name: "fat", age: 10) } struct People: Codable { var name: String var age: Int } ``` -------------------------------- ### Use Descriptive Property Names in ObservableDefaults Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md This Swift example shows best practices for naming properties in an ObservableDefaults class to ensure clarity. It defines settings with clear, descriptive names for notifications and retry attempts, persisted via UserDefaults. Requires ObservableDefaults macro; inputs are implicit defaults, outputs are persisted values; no limitations noted beyond standard UserDefaults constraints. ```swift @ObservableDefaults class Settings { var isNotificationsEnabled: Bool = true // Clear and descriptive var maxRetryAttempts: Int = 3 // Indicates purpose and type } ``` -------------------------------- ### Swift: Set Declaration Defaults for @ObservableDefaults Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Demonstrates how to declare default values for properties managed by @ObservableDefaults. These defaults serve as immutable fallbacks when keys are not found in UserDefaults or iCloud. The example shows current vs. default values and how properties revert to defaults upon external key deletion. ```swift import Foundation @propertyWrapper struct DefaultsBacked { let key: String let defaultValue: Value var wrappedValue: Value { get { UserDefaults.standard.object(forKey: key) as? Value ?? defaultValue } set { UserDefaults.standard.set(newValue, forKey: key) } } } // Example Usage: @ObservableDefaults(autoInit: false) class User { @DefaultsBacked(key: "username", defaultValue: "guest") var username: String @DefaultsBacked(key: "age", defaultValue: 18) var age: Int init(username: String, age: Int) { self.username = username self.age = age } } let user = User(username: "alice", age: 25) print("Current username: \(user.username)") // Current username: alice print("Default username: \(User.usernameDefault)") // Default username: guest (hypothetical access to default) print("Current age: \(user.age)") // Current age: 25 print("Default age: \(User.ageDefault)") // Default age: 18 (hypothetical access to default) user.username = "bob" print("Updated username: \(user.username)") // Updated username: bob // Simulate external deletion UserDefaults.standard.removeObject(forKey: "username") UserDefaults.standard.removeObject(forKey: "age") print("Username after deletion: \(user.username)") // Username after deletion: guest print("Age after deletion: \(user.age)") // Age after deletion: 18 ``` -------------------------------- ### Runtime Configuration with Initializer Parameters (Swift) Source: https://context7.com/fatbobman/observabledefaults/llms.txt Shows how to use different configurations at runtime by initializing `ConfigurableSettings` with different `UserDefaults` instances. This demonstrates flexibility in managing application settings based on environment. ```swift struct ConfigView: View { // Test environment with custom UserDefaults @State private var testSettings = ConfigurableSettings( userDefaults: UserDefaults(suiteName: "test")!, // Corrected: Add ! to force unwrap ignoreExternalChanges: true, prefix: "test_" ) // Production with standard UserDefaults @State private var prodSettings = ConfigurableSettings( userDefaults: .standard, ignoreExternalChanges: false, prefix: "prod_" ) var body: some View { VStack { Text("Test theme: (testSettings.theme)") Text("Prod theme: (prodSettings.theme)") } } } ``` -------------------------------- ### Swift: Recommended Architecture Pattern with ObservableDefaults Source: https://github.com/fatbobman/observabledefaults/blob/main/AI_REFERENCE.md Demonstrates a recommended architecture pattern using ObservableDefaults, including separate local and cloud settings classes, a unified app state composed of these settings, and SwiftUI integration for state management. It shows how to bind UI elements to observable properties. ```swift // ✅ Separate storage classes @ObservableDefaults class LocalSettings { var windowFrame: CGRect = .zero var recentFiles: [String] = [] var isDarkMode: Bool = false } @ObservableCloud class CloudSettings { var username: String = "Guest" var syncEnabled: Bool = true var preferences: UserPreferences = UserPreferences() } // ✅ Unified app state with composition @Observable class AppState { let local = LocalSettings() let cloud = CloudSettings() // App-specific transient state var isLoading: Bool = false var selectedTab: Tab = .home } // ✅ SwiftUI integration struct ContentView: View { @State private var appState = AppState() var body: some View { TabView(selection: $appState.selectedTab) { SettingsView(appState: appState) .tabItem { Label("Settings", systemImage: "gear") } .tag(Tab.settings) } } } struct SettingsView: View { let appState: AppState var body: some View { Form { Section("Local Settings") { Toggle("Dark Mode", isOn: $appState.local.isDarkMode) } Section("Cloud Settings") { TextField("Username", text: $appState.cloud.username) Toggle("Sync Enabled", isOn: $appState.cloud.syncEnabled) } } } } ``` -------------------------------- ### SwiftUI Preview Solutions in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Provides solutions for using @ObservableCloud classes with SwiftUI's #Preview. Includes adding a convenience initializer and using a singleton pattern. ```swift @ObservableCloud class CloudSettings { var item: Bool = true // Add this convenience initializer for Preview support convenience init() { self.init(prefix: nil, syncImmediately: false, developmentMode: true) } } #Preview { @Previewable var settings = CloudSettings() ContentView() .environment(settings) } ``` ```swift @ObservableCloud class CloudSettings { var item: Bool = true static let shared = CloudSettings() } #Preview { @Previewable var settings = CloudSettings.shared ContentView() .environment(settings) } ``` -------------------------------- ### Swift @ObservableCloud Macro Parameters Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Demonstrates configuring the @ObservableCloud macro with parameters like auto-initialization, key prefix, immediate synchronization, and development mode for testing. ```swift import Foundation @ObservableCloud( autoInit: true, prefix: "myApp_", observeFirst: false, syncImmediately: true, developmentMode: false ) class CloudSettings { @CloudKey(keyValueStoreKey: "user_theme") var theme: String = "light" } ``` -------------------------------- ### ObservableDefaults Macro - Advanced Configuration for UserDefaults Source: https://context7.com/fatbobman/observabledefaults/llms.txt Illustrates advanced configuration options for the @ObservableDefaults macro, including automatic initialization, external change observation, custom suite names, key prefixes, and instance limitations. ```swift import ObservableDefaults import SwiftUI // Advanced configuration with all parameters @ObservableDefaults( autoInit: true, // Generate initializer automatically ignoreExternalChanges: false, // Respond to external UserDefaults changes suiteName: "", // Use UserDefaults.standard prefix: "app_", // Prefix all keys with "app_" observeFirst: false, // Properties persist by default limitToInstance: true // Only observe this UserDefaults instance ) class AdvancedSettings { var theme: String = "light" var notifications: Bool = true } ``` -------------------------------- ### Configure ObservableCloud macro with parameters Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Demonstrates configuration of the @ObservableCloud macro with options like autoInit, prefix, observeFirst, syncImmediately, and developmentMode for iCloud key-value storage. ```swift @ObservableCloud( autoInit: true, prefix: "myApp_", observeFirst: false, syncImmediately: true, developmentMode: false ) class CloudSettings { @CloudKey(keyValueStoreKey: "user_theme") var theme: String = "light" } ``` -------------------------------- ### Swift Class Composition for Separate Storage Types Source: https://github.com/fatbobman/observabledefaults/blob/main/AI_REFERENCE.md Illustrates the correct approach for managing different storage types (UserDefaults and Cloud) by using separate classes and composing them within a unified observable class. ```swift // ✅ Separate classes for different storage types @ObservableDefaults class LocalSettings { var lastOpenedDocument: String = "" var windowFrame: CGRect = .zero } @ObservableCloud class CloudSettings { var username: String = "Guest" var theme: Theme = .light var preferences: UserPreferences = UserPreferences() } // ✅ Composition class for unified access @Observable class AppSettings { let local = LocalSettings() let cloud = CloudSettings() // Optional: Convenience computed properties var username: String { get { cloud.username } set { cloud.username = newValue } } } ``` -------------------------------- ### Composition Pattern for Unified State Management (Swift) Source: https://context7.com/fatbobman/observabledefaults/llms.txt Illustrates the composition pattern to combine local and cloud storage within a unified application state (`AppState`). This provides a central point of access to all application settings, promoting a consistent and organized approach to state management. ```swift @ObservableDefaults class LocalSettings { var windowFrame: CGRect = .zero var recentFiles: [String] = [] var isDarkMode: Bool = false var lastOpenedDocument: String = "" } @ObservableCloud class CloudSettings { var username: String = "Guest" var syncEnabled: Bool = true var preferences: UserPreferences = UserPreferences() var favoriteItems: [String] = [] } struct UserPreferences: Codable, Equatable { var emailNotifications: Bool = true var pushNotifications: Bool = true var theme: String = "auto" } @Observable class AppState { let local = LocalSettings() let cloud = CloudSettings() // Transient app-specific state var isLoading: Bool = false var selectedTab: Tab = .home var searchText: String = "" // Convenience computed properties var username: String { get { cloud.username } set { cloud.username = newValue } } var isDarkMode: Bool { get { local.isDarkMode } set { local.isDarkMode = newValue } } } enum Tab { case home, settings, profile } @main struct MyApp: App { @State private var appState = AppState() var body: some Scene { WindowGroup { ContentView() .environment(appState) } } } struct ContentView: View { @Environment(AppState.self) private var appState var body: some View { @Bindable var state = appState TabView(selection: $state.selectedTab) { HomeView() .tabItem { Label("Home", systemImage: "house") } .tag(Tab.home) SettingsView() .tabItem { Label("Settings", systemImage: "gear") } .tag(Tab.settings) } .overlay { if appState.isLoading { ProgressView() } } } } struct SettingsView: View { @Environment(AppState.self) private var appState var body: some View { @Bindable var state = appState Form { Section("Local Settings") { Toggle("Dark Mode", isOn: $state.local.isDarkMode) Text("Recent files: (state.local.recentFiles.count)") } Section("Cloud Settings") { TextField("Username", text: $state.cloud.username) Toggle("Sync Enabled", isOn: $state.cloud.syncEnabled) Toggle("Email Notifications",\n isOn: $state.cloud.preferences.emailNotifications) } } } } ``` -------------------------------- ### Initialize ObservableDefaults with custom parameters in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Demonstrates the initialization parameters for @ObservableDefaults including userDefaults instance, ignoreExternalChanges flag, and key prefix. These parameters provide flexibility for different usage scenarios. ```swift public init( userDefaults: UserDefaults? = nil, ignoreExternalChanges: Bool? = nil, prefix: String? = nil ) ``` -------------------------------- ### Configure ObservableDefaults macro with parameters Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Shows how to use the @ObservableDefaults macro with various configuration options like autoInit, ignoreExternalChanges, and prefix. Demonstrates usage for App Group cross-process synchronization. ```swift @ObservableDefaults(autoInit: false, ignoreExternalChanges: true, prefix: "myApp_") class Settings { @DefaultsKey(userDefaultsKey: "fullName") var name: String = "Fatbobman" } // For App Group cross-process synchronization @ObservableDefaults( suiteName: "group.myapp", prefix: "myapp_", limitToInstance: false ) class SharedSettings { var lastUpdate: Date = Date() } ``` -------------------------------- ### Initialize ObservableCloud with custom parameters in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Demonstrates the initialization parameters for @ObservableCloud including prefix for keys, syncImmediately flag for immediate synchronization, and developmentMode flag for testing with memory storage. ```swift public init( prefix: String? = nil, syncImmediately: Bool = false, developmentMode: Bool = false ) ``` -------------------------------- ### CI/CD Configuration for ObservableDefaults Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Shows how to configure CI/CD environments to skip macro validation when using ObservableDefaults. Includes commands for Swift CLI, xcodebuild, and fastlane. ```bash # For Swift CLI swift build -Xswiftc -skipMacroValidation swift test -Xswiftc -skipMacroValidation # For xcodebuild xcodebuild build OTHER_SWIFT_FLAGS="-skipMacroValidation" # For fastlane build_app( xcargs: "OTHER_SWIFT_FLAGS='-skipMacroValidation'" ) ``` -------------------------------- ### Custom Initializers in ObservableDefaults (Swift) Source: https://context7.com/fatbobman/observabledefaults/llms.txt Demonstrates custom initializers for `ObservableDefaults` and `ObservableCloud` classes to control initialization behavior and configure external change handling. Custom initializers allow for flexible configuration options and dependencies. Must call `observerStarter()` to enable external change observation. ```swift import ObservableDefaults // Disable auto-init to create custom initializer @ObservableDefaults(autoInit: false) class CustomInitSettings { var name: String = "Default" var count: Int = 0 init(customUserDefaults: UserDefaults, customPrefix: String) { // Custom initialization logic self._userDefaults = customUserDefaults self._prefix = customPrefix // MUST call observerStarter to enable external change observation observerStarter() } init(ignoringExternalChanges: Bool) { self._isExternalNotificationDisabled = ignoringExternalChanges observerStarter() } } // Custom init for cloud storage @ObservableCloud(autoInit: false) class CustomCloudSettings { var setting: String = "default" init(useProduction: Bool) { self._developmentMode_ = !useProduction self._syncImmediately = useProduction // Start cloud observation only in production mode if !_developmentMode_ { _cloudObserver = CloudObservation(host: self, prefix: _prefix) } } } ``` -------------------------------- ### ObservableDefaults Macro - Basic Usage for UserDefaults Source: https://context7.com/fatbobman/observabledefaults/llms.txt Demonstrates the basic usage of the @ObservableDefaults macro for automatically synchronizing properties with UserDefaults. It shows how to declare properties and use them within a SwiftUI view. ```swift import ObservableDefaults import SwiftUI // Basic usage: all properties automatically persist to UserDefaults @ObservableDefaults class AppSettings { var username: String = "Guest" var fontSize: Int = 14 var isDarkMode: Bool = false var lastLogin: Date = Date() } // Use in SwiftUI views struct SettingsView: View { @State private var settings = AppSettings() var body: some View { Form { TextField("Username", text: $settings.username) Stepper("Font Size: \(settings.fontSize)", value: $settings.fontSize, in: 10...24) Toggle("Dark Mode", isOn: $settings.isDarkMode) Text("Last login: \(settings.lastLogin.formatted())") } } } ``` -------------------------------- ### Use observe first mode with CloudKit Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Demonstrates observe first mode with @ObservableCloud where properties are observable by default but only explicitly marked properties are synced to iCloud. ```swift @ObservableCloud(observeFirst: true) public class CloudSettings { public var localSetting: String = "local" // Observable only public var tempData = "temp" // Observable only @CloudBacked(keyValueStoreKey: "user_theme") public var theme: String = "light" // Observable and synced to iCloud @Ignore public var cache = "cache" // Neither observable nor persisted } ``` -------------------------------- ### Swift: App Groups and Cross-Process Synchronization for UserDefaults Source: https://context7.com/fatbobman/observabledefaults/llms.txt Configures @ObservableDefaults to share UserDefaults between a main app and its extensions (like widgets) using App Groups. It emphasizes the critical need for a unique prefix for each group of settings to avoid key collisions and enables cross-process notifications via 'limitToInstance: false'. ```swift import ObservableDefaults // Widget-shared settings with cross-process sync @ObservableDefaults( suiteName: "group.com.mycompany.myapp", prefix: "widget_", // CRITICAL: Use unique prefix limitToInstance: false // Enable cross-process notifications ) class WidgetSharedSettings { var lastUpdateTime: Date = Date() var displayCount: Int = 0 var widgetData: String = "No data" } // Main app settings with App Group @ObservableDefaults( suiteName: "group.com.mycompany.myapp", prefix: "main_", // Different prefix for main app limitToInstance: false ) class MainAppSettings { var appVersion: String = "1.0" var totalLaunches: Int = 0 } // Usage in main app struct MainAppView: View { @State private var widgetSettings = WidgetSharedSettings() @State private var appSettings = MainAppSettings() var body: some View { VStack { Text("Widget updated: (widgetSettings.lastUpdateTime.formatted())") Text("Display count: (widgetSettings.displayCount)") Button("Update Widget Data") { widgetSettings.widgetData = "Updated at (Date())" widgetSettings.lastUpdateTime = Date() widgetSettings.displayCount += 1 } } } } // Usage in widget import WidgetKit struct MyWidget: Widget { let settings = WidgetSharedSettings() var body: some WidgetConfiguration { StaticConfiguration(kind: "MyWidget", provider: Provider()) { entry in WidgetView(data: settings.widgetData, count: settings.displayCount) } } } ``` -------------------------------- ### Customizing Behavior with Additional Macros for @ObservableCloud Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Shows how to use additional macros with @ObservableCloud for cloud-specific customization, including custom NSUbiquitousKeyValueStore keys and observable-only properties. ```swift @ObservableCloud public class CloudSettings { @CloudKey(keyValueStoreKey: "user_display_name") public var username: String = "Fatbobman" public var theme: String = "light" // Automatically cloud-backed @ObservableOnly public var localCache: String = "" // Observable only, not synced to cloud @Ignore public var temporaryData: String = "" // Neither observable nor persisted } ``` -------------------------------- ### Enable development mode for Cloud Storage in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Demonstrates how to enable development mode for @ObservableCloud macro which uses memory storage instead of CloudKit for testing. Development mode can be enabled explicitly, through SwiftUI Previews, or via environment variable. ```swift @ObservableCloud(developmentMode: true) class CloudSettings { var setting1: String = "value1" // Uses memory storage var setting2: Int = 42 // Uses memory storage } ``` -------------------------------- ### Swift @ObservableDefaults with Custom Key Prefix Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Shows how to apply a global prefix to all UserDefaults keys managed by the @ObservableDefaults macro. Also demonstrates using @DefaultsKey with a custom key alongside the prefix. ```swift import Foundation @ObservableDefaults(prefix: "MyApp_") class Settings { var apiEndpoint: String = "https://api.example.com" // Stored as "MyApp_apiEndpoint" in UserDefaults @DefaultsKey(userDefaultsKey: "server_url") var serverURL: String = "https://server.example.com" // Stored as "MyApp_server_url" in UserDefaults } ``` -------------------------------- ### Swift @ObservableDefaults Macro Parameters Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Configures the @ObservableDefaults macro with various parameters, including disabling auto-initialization, ignoring external changes, and setting a custom key prefix. ```swift import Foundation @ObservableDefaults(autoInit: false, ignoreExternalChanges: true, prefix: "myApp_") class Settings { @DefaultsKey(userDefaultsKey: "fullName") var name: String = "Fatbobman" } ``` -------------------------------- ### Cloud Storage with @ObservableCloud in Swift Source: https://context7.com/fatbobman/observabledefaults/llms.txt Demonstrates how to create observable classes that automatically synchronize data across user devices using iCloud Key-Value Store. Supports basic properties and custom configurations like development mode and key prefixes. Properties can be optionally excluded from cloud sync. ```swift import ObservableDefaults import SwiftUI // Basic cloud storage: properties sync across user's devices @ObservableCloud class CloudPreferences { var preferredLanguage: String = "en" var colorScheme: String = "auto" var syncEnabled: Bool = true } // Use identically to @ObservableDefaults in views struct CloudSettingsView: View { @State private var prefs = CloudPreferences() var body: some View { Form { Picker("Language", selection: $prefs.preferredLanguage) { Text("English").tag("en") Text("Spanish").tag("es") } Toggle("Sync Enabled", isOn: $prefs.syncEnabled) } } } // Development mode for testing without CloudKit setup @ObservableCloud(developmentMode: true) class TestCloudSettings { var testSetting: String = "test" // Uses memory storage, not iCloud var counter: Int = 0 } // Advanced cloud configuration @ObservableCloud( autoInit: true, // Generate initializer automatically prefix: "myapp_", // Prefix all cloud keys observeFirst: false, // Properties sync to cloud by default syncImmediately: true, // Force sync after each change developmentMode: false // Use real iCloud storage ) class AdvancedCloudSettings { @CloudKey(keyValueStoreKey: "user_theme_preference") var theme: String = "system" // Custom cloud key var fontSize: Int = 14 // Key: "myapp_fontSize" @ObservableOnly var localCache: String = "" // Not synced to cloud } // SwiftUI Preview support with convenience initializer @ObservableCloud class PreviewCloudSettings { var item: Bool = true // Add convenience init for @Previewable support convenience init() { self.init(prefix: nil, syncImmediately: false, developmentMode: true) } } #Preview { @Previewable var settings = PreviewCloudSettings() // Assuming ContentView and environment setup exist elsewhere // ContentView().environment(settings) Text("Preview Placeholder") // Placeholder for actual ContentView } ``` -------------------------------- ### Cloud Storage Integration with @ObservableCloud Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Demonstrates how to use the @ObservableCloud macro to synchronize data across devices using iCloud. Properties are automatically synced with NSUbiquitousKeyValueStore and support optional values. ```swift import ObservableDefaults @ObservableCloud class CloudSettings { var number = 1 var color: Colors = .red var style: FontStyle = .style1 var cloudName: String? = nil // Optional support } ``` -------------------------------- ### ObservableDefaults Macro - Custom Keys and Mixed Persistence Source: https://context7.com/fatbobman/observabledefaults/llms.txt Shows how to use @ObservableDefaults with custom UserDefaults keys using @DefaultsKey, observe properties without persistence using @ObservableOnly, and exclude properties from observation and persistence using @Ignore. ```swift import ObservableDefaults import SwiftUI // Custom UserDefaults keys and mixed persistence @ObservableDefaults class MixedSettings { @DefaultsKey(userDefaultsKey: "user_display_name") var username: String = "User" // Stored with custom key var age: Int = 25 // Stored with key "age" @ObservableOnly var tempSelection: Int = 0 // Observable only, not persisted @Ignore var privateData: String = "" // Not observable, not persisted } ``` -------------------------------- ### Swift: Property Accessor Generation for ObservableDefaults Source: https://github.com/fatbobman/observabledefaults/blob/main/AI_REFERENCE.md Demonstrates the Swift code generated by property macros for accessing and modifying backed properties. It includes getter logic that reads from a wrapper and setter logic that updates the wrapper and internal state, ensuring view updates via `access()` and `withMutation()`. ```swift private var _propertyName: Type = defaultValue var propertyName: Type { get { access(keyPath: \.propertyName) return Wrapper.getValue(key, _propertyName, store) } set { withMutation(keyPath: \.propertyName) { if shouldSetValue(_propertyName, newValue) { Wrapper.setValue(key, newValue, store) _propertyName = newValue } } } } ``` -------------------------------- ### Integrate UserDefaults and iCloud Settings in SwiftUI View Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Presents a SwiftUI view that utilizes both UserDefaults-backed settings (@ObservableDefaults) and iCloud-backed settings (@ObservableCloud). It demonstrates how to bind UI elements to properties from both storage mechanisms. ```swift import SwiftUI struct ContentView: View { @State var settings = Settings() // UserDefaults-backed @State var cloudSettings = CloudSettings() // iCloud-backed var body: some View { VStack { // Local settings Text("Name: \(settings.name)") TextField("Enter name", text: $settings.name) // Cloud-synchronized settings Text("Username: \(cloudSettings.username)") TextField("Enter username", text: $cloudSettings.username) } .padding() } ``` -------------------------------- ### Define Settings with @ObservableDefaults Macro in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Demonstrates how to use the @ObservableDefaults macro to associate Swift properties with UserDefaults. This macro automatically handles key association, external change listening, and precise SwiftUI notifications for local data persistence. ```swift import ObservableDefaults @ObservableDefaults class Settings { var name: String = "Fatbobman" var age: Int = 20 var nickname: String? = nil // Optional support } ``` -------------------------------- ### Codable Custom Type Support for UserDefaults and iCloud in Swift Source: https://context7.com/fatbobman/observabledefaults/llms.txt Enables storing complex custom types conforming to Codable with both UserDefaults and iCloud Key-Value Store synchronization. Defines `UserProfile` and `AppearanceSettings` structs, then demonstrates their usage with @ObservableDefaults and @ObservableCloud classes. ```swift import ObservableDefaults import Foundation import SwiftUI // Define custom Codable types struct UserProfile: Codable, Equatable { var name: String var email: String var age: Int } struct AppearanceSettings: Codable, Equatable { var primaryColor: String var secondaryColor: String var fontSize: Double } // UserDefaults storage with Codable types @ObservableDefaults class ProfileStore { var currentUser: UserProfile = UserProfile( name: "John Doe", email: "john@example.com", age: 30 ) var appearance: AppearanceSettings = AppearanceSettings( primaryColor: "#007AFF", secondaryColor: "#FF9500", fontSize: 16.0 ) } // iCloud storage with Codable types @ObservableCloud class CloudProfileStore { var userProfile: UserProfile = UserProfile( name: "Jane", email: "jane@example.com", age: 28 ) var preferences: AppearanceSettings = AppearanceSettings( primaryColor: "#34C759", secondaryColor: "#FF3B30", fontSize: 14.0 ) } // Usage in SwiftUI struct ProfileView: View { @State private var store = ProfileStore() // Helper extensions for Color <-> Hex conversion (assuming these exist) // extension Color { static func fromHex(_ hex: String) -> Color { ... } } // extension Color { func toHex() -> String { ... } } var body: some View { Form { Section("User Info") { TextField("Name", text: $store.currentUser.name) TextField("Email", text: $store.currentUser.email) Stepper("Age: \(store.currentUser.age)", value: $store.currentUser.age, in: 1...120) } Section("Appearance") { ColorPicker("Primary", selection: Binding( get: { /* Color(hex: store.appearance.primaryColor) */ Color.blue }, // Placeholder for actual conversion set: { store.appearance.primaryColor = /* $0.toHex() */ "#0000FF" } // Placeholder for actual conversion )) } } } } // Placeholder for PreviewProvider if needed, similar to the previous snippet #Preview { ProfileView() } ``` -------------------------------- ### Using in SwiftUI Views Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Shows how to integrate both @ObservableDefaults and @ObservableCloud classes in SwiftUI views. The properties are bound to UI elements for real-time updates. ```swift import SwiftUI struct ContentView: View { @State var settings = Settings() // UserDefaults-backed @State var cloudSettings = CloudSettings() // iCloud-backed var body: some View { VStack { // Local settings Text("Name: \(settings.name)") TextField("Enter name", text: $settings.name) // Cloud-synchronized settings Text("Username: \(cloudSettings.username)") TextField("Enter username", text: $cloudSettings.username) } .padding() } } ``` -------------------------------- ### Swift: Observe First Mode with UserDefaults and CloudKit Source: https://context7.com/fatbobman/observabledefaults/llms.txt Demonstrates how to use @ObservableDefaults and @ObservableCloud with the 'observeFirst: true' option. This mode makes properties observable by default but only persists/syncs those explicitly marked with @DefaultsBacked or @CloudBacked. Properties marked with @Ignore are neither observable nor persisted. ```swift import ObservableDefaults // UserDefaults Observe First mode @ObservableDefaults(observeFirst: true) class ObserveFirstSettings { var temporarySelection: Int = 0 // Observable only var currentView: String = "home" // Observable only @DefaultsBacked // Explicitly persist this var savedTheme: String = "light" @DefaultsBacked(userDefaultsKey: "user_name") var username: String = "User" // Observable and persisted @Ignore var internalState: Bool = false // Neither observable nor persisted } // iCloud Observe First mode @ObservableCloud(observeFirst: true) class CloudObserveFirstSettings { var localTemporaryData: String = "temp" // Observable only var uiState: Int = 0 // Observable only @CloudBacked // Explicitly sync to cloud var cloudSyncedData: String = "synced" @CloudBacked(keyValueStoreKey: "shared_pref") var sharedPreference: Bool = true // Observable and cloud-synced @Ignore var privateCache: [String] = [] // Not observable or synced } // Usage scenario: mix local UI state with persistent settings struct ObserveFirstView: View { @State private var settings = ObserveFirstSettings() var body: some View { VStack { // temporarySelection changes don't persist across launches Picker("Temporary", selection: $settings.temporarySelection) { Text("Option 1").tag(0) Text("Option 2").tag(1) } // savedTheme persists across launches Picker("Theme (Saved)", selection: $settings.savedTheme) { Text("Light").tag("light") Text("Dark").tag("dark") } } } } ``` -------------------------------- ### Swift @ObservableCloud Observe First Mode Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Demonstrates @ObservableCloud in 'Observe First Mode', where properties are observable by default and only synchronized to iCloud when explicitly marked with @CloudBacked. ```swift import Foundation @ObservableCloud(observeFirst: true) public class CloudSettings { public var localSetting: String = "local" // Observable only public var tempData = "temp" // Observable only @CloudBacked(keyValueStoreKey: "user_theme") public var theme: String = "light" // Observable and synced to iCloud @Ignore public var cache = "cache" // Neither observable nor persisted } ``` -------------------------------- ### Define Cloud Settings with @ObservableCloud Macro in Swift Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Illustrates the usage of the @ObservableCloud macro for managing data synchronized via iCloud's Key-Value Store. This macro automatically handles synchronization across devices and provides the same observation benefits as @ObservableDefaults. ```swift import ObservableDefaults @ObservableCloud class CloudSettings { var username: String = "Fatbobman" var theme: String = "light" var isFirstLaunch: Bool = true var cloudNotes: String? = nil // Optional support } ``` -------------------------------- ### Swift @ObservableDefaults Observe First Mode Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Configures @ObservableDefaults to operate in 'Observe First Mode', making properties observable by default and requiring explicit marking (@DefaultsBacked) for persistence to UserDefaults. ```swift import Foundation @ObservableDefaults(observeFirst: true) public class LocalSettings { public var name: String = "fat" // Observable only public var age = 109 // Observable only @DefaultsBacked(userDefaultsKey: "myHeight") public var height = 190 // Observable and persisted to UserDefaults @Ignore public var weight = 10 // Neither observable nor persisted } ``` -------------------------------- ### Use @ObservableDefaults Settings in SwiftUI View Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md Shows how to integrate a class marked with @ObservableDefaults into a SwiftUI view using the @State property wrapper. This allows for seamless data binding and UI updates based on changes to UserDefaults. ```swift import SwiftUI struct ContentView: View { @State var settings = Settings() var body: some View { VStack { Text("Name: \(settings.name)") TextField("Enter name", text: $settings.name) Text("Age: \(settings.age)") Stepper("Age", value: $settings.age, in: 0...120) } .padding() } ``` -------------------------------- ### Support optional types in observable macros Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Shows how both @ObservableDefaults and @ObservableCloud macros support Optional properties with various data types including custom keys. ```swift @ObservableDefaults class SettingsWithOptionals { var username: String? = nil var age: Int? = 25 var isEnabled: Bool? = true @DefaultsKey(userDefaultsKey: "custom-optional-key") var customOptional: String? = nil } @ObservableCloud class CloudSettingsWithOptionals { var cloudUsername: String? = nil var preferences: [String]? = nil @CloudKey(keyValueStoreKey: "user-settings") var userSettings: [String: String]? = nil } ``` -------------------------------- ### Provide Sensible Defaults in ObservableDefaults Source: https://github.com/fatbobman/observabledefaults/blob/main/Sources/ObservableDefaults/ObservableDefaults.docc/ObservableDefaults.md This Swift snippet illustrates providing sensible default values for configuration properties in an ObservableDefaults class. It sets defaults for cache size and request timeout, ensuring meaningful fallbacks. Depends on ObservableDefaults framework; inputs are declaration defaults, outputs are persisted or default values; limitations include immutable defaults once set. ```swift @ObservableDefaults class AppConfiguration { var cacheSize: Int = 100_000_000 // 100MB default var requestTimeout: TimeInterval = 30.0 // 30 seconds default } ``` -------------------------------- ### App Group UserDefaults with Unique Prefixes Source: https://github.com/fatbobman/observabledefaults/blob/main/README.md Demonstrates how to use @ObservableDefaults with `limitToInstance: false` and unique prefixes to manage separate App Group UserDefaults suites. This prevents unintended data modification by filtering notifications based on the provided prefix. ```swift // App Group suite @ObservableDefaults( suiteName: "group.myapp", prefix: "myapp_", // Only respond to keys starting with "myapp_" limitToInstance: false ) class AppGroupSettings { var sharedData: String = "data" // Stored as "myapp_sharedData" } // Different App Group suite @ObservableDefaults( suiteName: "group.anotherapp", prefix: "anotherapp_", // Only respond to keys starting with "anotherapp_" limitToInstance: false ) class AnotherAppSettings { var sharedData: String = "other" // Stored as "anotherapp_sharedData" } ```