### Dictionary Example with AnySerializable Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Illustrates using a dictionary with Defaults.AnySerializable values. The dictionary key must be String, and values can be of various types. ```swift extension Defaults.Keys { static let magic = Key<[String: Defaults.AnySerializable]>("magic", default: [:]) } enum Mime: String, Defaults.Serializable { case json = "application/json" } Defaults[.magic]["unicorn"] = "🦄" if let value: String = Defaults[.magic]["unicorn"]?.get() { print(value) //=> "🦄" } Defaults[.magic]["number"] = 3 Defaults[.magic]["boolean"] = true Defaults[.magic]["enum"] = Defaults.AnySerializable(Mime.json) if let mimeType: Mime = Defaults[.magic]["enum"]?.get() { print(mimeType.rawValue) //=> "application/json" } ``` -------------------------------- ### Codable Type Example Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/SupportedTypes.md Any type conforming to Codable can be stored. Ensure the struct or class conforms to both Codable and Defaults.Serializable. ```swift struct User: Codable, Defaults.Serializable { let name: String age: String } extension Defaults.Keys { static let user = Key("user", default: .init(name: "Hello", age: "24")) } Defaults[.user].name //=> "Hello" ``` -------------------------------- ### Declare a new key with a default value Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Declare a key with its type and a default value. The key name must be ASCII, not start with '@', and cannot contain a dot (.). ```swift import Defaults extension Defaults.Keys { static let quality = Key("quality", default: 0.8) // ^ ^ ^ ^ // Key Type UserDefaults name Default value } ``` -------------------------------- ### Enum with String Raw Value Example Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/SupportedTypes.md Enums with raw values that conform to supported types work automatically. Ensure the raw value is a supported type. ```swift enum DurationKeys: String, Defaults.Serializable { case tenMinutes = "10 Minutes" case halfHour = "30 Minutes" case oneHour = "1 Hour" } extension Defaults.Keys { static let defaultDuration = Key("defaultDuration", default: .oneHour) } Defaults[.defaultDuration].rawValue //=> "1 Hour" ``` -------------------------------- ### Accessing Defaults and UserDefaults keys Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/FAQ.md Demonstrates how Defaults keys and standard UserDefaults calls access the same underlying data. ```swift extension Defaults.Keys { static let theme = Key("theme", default: "light") } // These access the same value Defaults[.theme] = "dark" UserDefaults.standard.string(forKey: "theme") //=> "dark" ``` -------------------------------- ### Using a custom UserDefaults suite Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Configure Defaults to use a custom `UserDefaults` suite by providing a `suite` parameter when declaring the key. ```swift let extensionDefaults = UserDefaults(suiteName: "com.unicorn.app")! extension Defaults.Keys { static let isUnicorn = Key("isUnicorn", default: true, suite: extensionDefaults) } Defaults[.isUnicorn] //=> true // Or extensionDefaults[.isUnicorn] //=> true ``` -------------------------------- ### Observe key changes using async/await Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Observe changes to keys using async/await. This provides strongly-typed change objects, unlike native `UserDefaults` observation. ```swift extension Defaults.Keys { static let isUnicornMode = Key("isUnicornMode", default: false) } Task { for await value in Defaults.updates(.isUnicornMode) { print("Value:", value) } } ``` -------------------------------- ### Configure Custom UserDefaults Suite Source: https://context7.com/sindresorhus/defaults/llms.txt Use custom suites for sharing data between an app and its extensions. ```swift import Defaults let sharedDefaults = UserDefaults(suiteName: "group.com.myapp.shared")! extension Defaults.Keys { static let sharedToken = Key("sharedToken", suite: sharedDefaults) static let syncEnabled = Key("syncEnabled", default: true, suite: sharedDefaults) } // Access via Defaults Defaults[.sharedToken] = "abc123" // Or directly via the suite sharedDefaults[.syncEnabled] // => true ``` -------------------------------- ### Observing Defaults Changes with Async/Await Source: https://context7.com/sindresorhus/defaults/llms.txt Monitor value changes using modern async/await syntax with `Defaults.updates()`. This allows for observing single keys, multiple keys with values, or just notifications of changes. ```swift import Defaults extension Defaults.Keys { static let isUnicornMode = Key("isUnicornMode", default: false) static let username = Key("username", default: "Guest") } // Observe a single key Task { for await value in Defaults.updates(.isUnicornMode) { print("Unicorn mode changed to: \(value)") } } // Observe multiple keys with values Task { for await (unicornMode, username) in Defaults.updates(.isUnicornMode, .username) { print("Settings updated - Unicorn: \(unicornMode), User: \(username)") } } // Observe multiple keys without values (just notifications) Task { for await _ in Defaults.updates([.isUnicornMode, .username]) { print("One of the settings changed") } } ``` -------------------------------- ### Define and Access Defaults Keys Source: https://github.com/sindresorhus/defaults/blob/main/readme.md Define keys in an extension of Defaults.Keys and access them using the Defaults subscript. ```swift import Defaults extension Defaults.Keys { static let quality = Key("quality", default: 0.8) } Defaults[.quality] //=> 0.8 Defaults[.quality] = 0.5 //=> 0.5 ``` -------------------------------- ### Migrate from AppStorage to Defaults Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/FAQ.md Centralize key definitions and default values when migrating from AppStorage. ```swift struct SettingsView: View { @AppStorage("showPreview") var showPreview = true var body: some View { Toggle("Show Preview", isOn: $showPreview) } } ``` ```swift extension Defaults.Keys { static let showPreview = Key("showPreview", default: true) } struct SettingsView: View { @Default(.showPreview) var showPreview var body: some View { Toggle("Show Preview", isOn: $showPreview) } } ``` -------------------------------- ### Store Collections and Dictionaries Source: https://context7.com/sindresorhus/defaults/llms.txt Manage arrays, sets, and dictionaries directly using Defaults. ```swift import Defaults extension Defaults.Keys { static let favoriteColors = Key<[String]>("favoriteColors", default: ["blue", "green"]) static let visitedPages = Key>("visitedPages", default: []) static let scores = Key<[String: Int]>("scores", default: [:]) } // Arrays Defaults[.favoriteColors].append("red") // Sets Defaults[.visitedPages].insert("home") Defaults[.visitedPages].insert("settings") // Dictionaries Defaults[.scores]["player1"] = 100 Defaults[.scores]["player2"] = 85 ``` -------------------------------- ### Use keys directly without extension Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Keys do not need to be attached to `Defaults.Keys`. They can be declared and used directly. ```swift let isUnicorn = Defaults.Key("isUnicorn", default: true) Defaults[isUnicorn] //=> true ``` -------------------------------- ### Configure Defaults for App Groups Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/FAQ.md Use a custom suite name to share data between apps in an App Group. ```swift let sharedDefaults = UserDefaults(suiteName: "group.com.example.app")! extension Defaults.Keys { static let sharedCounter = Key("counter", default: 0, suite: sharedDefaults) } ``` -------------------------------- ### Register Custom Keys Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Define keys for custom types and collections to enable type-safe access via Defaults. ```swift extension Defaults.Keys { static let user = Key("user", default: .init(name: "Hello", age: "24")) static let users = Key>("users", default: Set([.init(name: "Hello", age: "24")])) static let usersArray = Key<[User]>("usersArray", default: [.init(name: "Hello", age: "24")]) static let usersByIdentifier = Key<[String: User]>("usersByIdentifier", default: ["user": .init(name: "Hello", age: "24")]) } Defaults[.user].name //=> "Hello" Defaults[.users].first?.name //=> "Hello" Defaults[.usersArray][0].name //=> "Hello" Defaults[.usersByIdentifier]["user"]?.name //=> "Hello" ``` -------------------------------- ### Primitive Assignments with AnySerializable Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Demonstrates assigning primitive types to Defaults.AnySerializable. This key can store various types. ```swift let any = Defaults.Key("anyKey", default: 1) Defaults[any] = "🦄" ``` -------------------------------- ### Import Defaults Without Prefix Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/SwiftUIIntegration.md To avoid importing `Defaults` in every file, you can use type aliases. Add these aliases to a file in your project to access `Defaults` and `@Default` globally without needing explicit imports. ```swift import Defaults typealias Defaults = _Defaults typealias Default = _Default ``` -------------------------------- ### SwiftUI Integration with @Default Source: https://context7.com/sindresorhus/defaults/llms.txt Use the `@Default` property wrapper for automatic view updates when stored values change. Ensure your Defaults.Keys extension is defined. ```swift import SwiftUI import Defaults extension Defaults.Keys { static let volume = Key("volume", default: 0.5) static let isDarkMode = Key("isDarkMode", default: false) } struct SettingsView: View { @Default(.volume) var volume @Default(.isDarkMode) var isDarkMode var body: some View { Form { Section("Audio") { Slider(value: $volume, in: 0...1) Text("Volume: \(Int(volume * 100))%") } Section("Appearance") { Toggle("Dark Mode", isOn: $isDarkMode) } Section { Button("Reset to Defaults") { _volume.reset() _isDarkMode.reset() } } } } } ``` -------------------------------- ### Working with Typed Values using AnySerializable Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Shows how to store and retrieve strongly typed values using Defaults.AnySerializable. Requires the enum to conform to Defaults.Serializable. ```swift enum Mime: String, Defaults.Serializable { case json = "application/json" case stream = "application/octet-stream" } let any = Defaults.Key("anyKey", default: Defaults.AnySerializable(Mime.json)) if let mimeType: Mime = Defaults[any].get() { print(mimeType.rawValue) //=> "application/json" } Defaults[any].set(Mime.stream) if let mimeType: Mime = Defaults[any].get() { print(mimeType.rawValue) //=> "application/octet-stream" } ``` -------------------------------- ### Create a Defaults Bridge Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Implement the Defaults.Bridge protocol to define how a custom type is serialized and deserialized for storage. ```swift struct UserBridge: Defaults.Bridge { typealias Value = User typealias Serializable = [String: String] public func serialize(_ value: Value?) -> Serializable? { guard let value else { return nil } return [ "name": value.name, "age": value.age ] } public func deserialize(_ object: Serializable?) -> Value? { guard let object, let name = object["name"], let age = object["age"] else { return nil } return User( name: name, age: age ) } } ``` -------------------------------- ### Observing Defaults Changes with Combine Source: https://context7.com/sindresorhus/defaults/llms.txt Use Combine publishers for reactive observation of defaults changes. This is useful for integrating with Combine-based architectures and managing state updates. ```swift import Defaults import Combine extension Defaults.Keys { static let searchQuery = Key("searchQuery", default: "") } class SearchViewModel: ObservableObject { @Published var results: [String] = [] private var cancellables = Set() init() { Defaults.publisher(.searchQuery) .map(\.newValue) .debounce(for: .milliseconds(300), scheduler: RunLoop.main) .removeDuplicates() .sink { self.performSearch(query: $0) } .store(in: &cancellables) } private func performSearch(query: String) { // Perform search... } } ``` -------------------------------- ### Create Defaults.Toggle Component for Boolean Settings Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/SwiftUIIntegration.md Utilize the `Defaults.Toggle` component as a SwiftUI wrapper for `Toggle` to easily create boolean settings linked to Defaults keys. This component simplifies the process of managing boolean preferences. ```swift extension Defaults.Keys { static let showAllDayEvents = Key("showAllDayEvents", default: false) } struct ShowAllDayEventsSetting: View { var body: some View { Defaults.Toggle("Show All-Day Events", key: .showAllDayEvents) } } ``` -------------------------------- ### Accessing values via standard UserDefaults Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Defaults keys can also be accessed directly through `UserDefaults.standard`. ```swift extension Defaults.Keys { static let isUnicorn = Key("isUnicorn", default: true) } UserDefaults.standard[.isUnicorn] //=> true ``` -------------------------------- ### Use @ObservableDefault Macro in Observable Classes Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/SwiftUIIntegration.md Employ the `@ObservableDefault` macro to integrate Defaults values into `@Observable` classes within the Observation framework. Import `Defaults` and `DefaultsMacros`, and use `@ObservationIgnored` to prevent conflicts. Be aware that using macros can increase build times. ```swift import Defaults import DefaultsMacros @Observable final class UnicornManager { @ObservableDefault(.hasUnicorn) @ObservationIgnored var hasUnicorn: Bool } ``` -------------------------------- ### Declare Defaults Keys Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Documentation.md Define keys with associated types and default values within the Defaults.Keys namespace. ```swift import Defaults extension Defaults.Keys { static let quality = Key("quality", default: 0.8) } ``` -------------------------------- ### Use Dynamic Default Values Source: https://context7.com/sindresorhus/defaults/llms.txt Provide a closure to compute default values at runtime. ```swift import Defaults import AVFoundation extension Defaults.Keys { static let camera = Key("camera") { .default(for: .video) } static let defaultLocale = Key("defaultLocale") { Locale.current.identifier } } // The closure is evaluated each time the default is needed let camera = Defaults[.camera] ``` -------------------------------- ### Declare Optional Keys Source: https://context7.com/sindresorhus/defaults/llms.txt Define keys without default values by using optional types, which default to nil. ```swift import Defaults extension Defaults.Keys { static let name = Key("name") static let lastLoginDate = Key("lastLoginDate") } // Usage if let name = Defaults[.name] { print("Welcome back, \(name)") } else { print("Welcome, new user") } Defaults[.name] = "Alice" Defaults[.lastLoginDate] = Date() ``` -------------------------------- ### Access and Modify Values Source: https://context7.com/sindresorhus/defaults/llms.txt Use subscript syntax to read and write values with compile-time type checking. ```swift import Defaults // Reading values let quality = Defaults[.quality] // => 0.8 // Writing values Defaults[.quality] = 0.5 // => 0.5 // Compound assignment works Defaults[.launchCount] += 1 // Type safety - this won't compile: // Defaults[.quality] = "invalid" // Error: Cannot assign String to Double ``` -------------------------------- ### Define a Custom Type Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Define a struct that conforms to Hashable to enable storage in sets or dictionaries. ```swift struct User: Hashable { let name: String let age: String } ``` -------------------------------- ### Callback-Based Observation of Defaults Source: https://context7.com/sindresorhus/defaults/llms.txt Use traditional callback-based observation with explicit lifetime management. The `Defaults.observe` method takes a closure that is executed when the observed default value changes. ```swift import Defaults extension Defaults.Keys { static let volume = Key("volume", default: 0.5) } class AudioManager { private var observation: Defaults.Observation? func startObserving() { observation = Defaults.observe(.volume) { print("Volume changed from \($0.oldValue) to \($0.newValue)") self.updateAudioLevel($0.newValue) } } // Automatically tie observation to object lifetime func startObservingWithLifetime() { Defaults.observe(.volume) { print("Volume: \($0.newValue)") }.tieToLifetime(of: self) } private func updateAudioLevel(_ level: Double) { // Update audio... } deinit { observation?.invalidate() } } ``` -------------------------------- ### Conform to Defaults.Serializable Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Associate the custom bridge with the type by conforming to the Defaults.Serializable protocol. ```swift extension User: Defaults.Serializable { static let bridge = UserBridge() } ``` -------------------------------- ### Registering default values with UserDefaults Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md When a `Defaults/Key` is created, its default value is automatically registered with `UserDefaults.standard`. This is useful for Interface Builder bindings. ```swift extension Defaults.Keys { static let isUnicornMode = Key("isUnicornMode", default: true) } print(UserDefaults.standard.bool(forKey: Defaults.Keys.isUnicornMode.name)) //=> true ``` -------------------------------- ### Declare Keys with Default Values Source: https://context7.com/sindresorhus/defaults/llms.txt Extend Defaults.Keys to define strongly-typed keys with associated default values. ```swift import Defaults extension Defaults.Keys { static let quality = Key("quality", default: 0.8) static let username = Key("username", default: "Guest") static let isUnicornMode = Key("isUnicornMode", default: false) static let launchCount = Key("launchCount", default: 0) } ``` -------------------------------- ### Use Defaults outside of SwiftUI Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/FAQ.md Defaults can be used in any Swift code, including support for async/await observation. ```swift // In any Swift code Defaults[.userName] = "Alice" // Observe changes with async/await Task { for await value in Defaults.updates(.userName) { print("User name changed to:", value) } } ``` -------------------------------- ### Resetting Keys to Default Values Source: https://context7.com/sindresorhus/defaults/llms.txt Reset individual keys, multiple keys, or all keys back to their default values or nil. ```swift import Defaults extension Defaults.Keys { static let volume = Key("volume", default: 0.5) static let brightness = Key("brightness", default: 0.8) static let username = Key("username") } // Reset single key Defaults[.volume] = 1.0 Defaults.reset(.volume) print(Defaults[.volume]) // => 0.5 // Reset multiple keys Defaults.reset(.volume, .brightness) // Reset by key name (useful for dynamic keys) Defaults.reset("volume", "brightness") // Reset optional key (becomes nil) Defaults[.username] = "Alice" Defaults.reset(.username) print(Defaults[.username]) // => nil // Remove all user defaults Defaults.removeAll() ``` -------------------------------- ### Declare an optional key Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Declare optional keys when no default value is desired upfront. The default value for such keys will be `nil`. ```swift extension Defaults.Keys { static let name = Key("name") } if let name = Defaults[.name] { print(name) } ``` -------------------------------- ### Use Defaults in SwiftUI Source: https://github.com/sindresorhus/defaults/blob/main/readme.md Use the @Default property wrapper to bind UserDefaults values directly to SwiftUI views. ```swift struct ContentView: View { @Default(.quality) var quality var body: some View { Slider(value: $quality, in: 0...1) } } ``` -------------------------------- ### Resetting a key to its default value Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Reset a key to its predefined default value using `Defaults.reset()`. This also works for optional keys, resetting them to `nil`. ```swift extension Defaults.Keys { static let isUnicornMode = Key("isUnicornMode", default: false) } Defaults[.isUnicornMode] = true //=> true Defaults.reset(.isUnicornMode) Defaults[.isUnicornMode] //=> false ``` -------------------------------- ### AnySerializable for Dynamic Types Source: https://context7.com/sindresorhus/defaults/llms.txt Use AnySerializable to store values of different types within the same key. ```swift import Defaults extension Defaults.Keys { static let dynamicValue = Key("dynamicValue", default: 42) } // Store different types Defaults[.dynamicValue] = 100 Defaults[.dynamicValue] = "Hello" Defaults[.dynamicValue] = true Defaults[.dynamicValue] = [1, 2, 3] // Retrieve with type casting if let intValue: Int = Defaults[.dynamicValue].get() { print("Integer: \(intValue)") } if let stringValue: String = Defaults[.dynamicValue].get() { print("String: \(stringValue)") } // Or specify type explicitly let value = Defaults[.dynamicValue].get(Int.self) ``` -------------------------------- ### Store optional values Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/FAQ.md Create keys with optional types by omitting the default value. ```swift extension Defaults.Keys { static let userName = Key("userName") } // Default value is nil Defaults[.userName] //=> nil // Set a value Defaults[.userName] = "Alice" // Reset to nil Defaults.reset(.userName) ``` -------------------------------- ### Store dictionaries with AnySerializable Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/FAQ.md Use AnySerializable to store dictionaries with mixed value types. ```swift extension Defaults.Keys { static let settings = Key<[String: Defaults.AnySerializable]>("settings", default: [:]) } Defaults[.settings]["theme"] = "dark" Defaults[.settings]["fontSize"] = 14 Defaults[.settings]["enabled"] = true ``` -------------------------------- ### Access and modify key values Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Access values as a subscript on the `Defaults` global. Values can be read, assigned, or modified directly. ```swift Defaults[.quality] //=> 0.8 Defaults[.quality] = 0.5 //=> 0.5 Defaults[.quality] += 0.1 //=> 0.6 ``` ```swift Defaults[.quality] = "🦄" //=> [Cannot assign value of type 'String' to type 'Double'] ``` -------------------------------- ### Listen for Changes on Defaults.Toggle Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/SwiftUIIntegration.md Observe changes directly on the `Defaults.Toggle` component using the `.onChange` modifier. This modifier must be attached directly to `Defaults.Toggle` and is distinct from the standard `View#onChange()` modifier. ```swift struct ShowAllDayEventsSetting: View { var body: some View { Defaults.Toggle("Show All-Day Events", key: .showAllDayEvents) // Note: This must be directly attached to Defaults.Toggle, not a regular View#onChange() .onChange { print("Value", $0) } } } ``` -------------------------------- ### Custom Bridge for Unsupported Types Source: https://context7.com/sindresorhus/defaults/llms.txt Implement the Defaults.Bridge protocol to serialize and deserialize custom types not natively supported by UserDefaults. ```swift import Defaults struct User { var id: Int var username: String var email: String } struct UserBridge: Defaults.Bridge { typealias Value = User typealias Serializable = [String: Any] func serialize(_ value: Value?) -> Serializable? { guard let value else { return nil } return [ "id": value.id, "username": value.username, "email": value.email ] } func deserialize(_ object: Serializable?) -> Value? { guard let object, let id = object["id"] as? Int, let username = object["username"] as? String, let email = object["email"] as? String else { return nil } return User(id: id, username: username, email: email) } } extension User: Defaults.Serializable { static let bridge = UserBridge() } extension Defaults.Keys { static let currentUser = Key("currentUser") } // Usage Defaults[.currentUser] = User(id: 1, username: "alice", email: "alice@example.com") ``` -------------------------------- ### Store Codable Types Source: https://context7.com/sindresorhus/defaults/llms.txt Store custom types by conforming them to Codable and Defaults.Serializable. ```swift import Defaults enum Theme: String, Codable, Defaults.Serializable { case light case dark case system } struct UserSettings: Codable, Defaults.Serializable { var fontSize: Int var theme: Theme var notifications: Bool } extension Defaults.Keys { static let theme = Key("theme", default: .system) static let userSettings = Key("userSettings", default: UserSettings( fontSize: 14, theme: .system, notifications: true )) } // Usage Defaults[.theme] = .dark Defaults[.userSettings].fontSize = 16 ``` -------------------------------- ### Observe changes in ObservableObject Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/FAQ.md Use the @ObservableDefault macro for observable objects instead of the standard property wrapper. ```swift import Defaults import DefaultsMacros @Observable final class Settings { @ObservableDefault(.theme) @ObservationIgnored var theme: String } ``` -------------------------------- ### iCloud Synchronization Source: https://context7.com/sindresorhus/defaults/llms.txt Enable automatic iCloud synchronization for specific keys and manage sync state. ```swift import Defaults extension Defaults.Keys { // Enable iCloud sync when declaring the key static let isPremiumUser = Key("isPremiumUser", default: false, iCloud: true) static let favoriteTheme = Key("favoriteTheme", default: "default", iCloud: true) } // Changes automatically sync to other devices Defaults[.isPremiumUser] = true // Wait for sync completion if needed Task { Defaults[.favoriteTheme] = "dark" await Defaults.iCloud.waitForSyncCompletion() print("Theme synced to iCloud") } // Dynamically add/remove keys from iCloud sync extension Defaults.Keys { static let dynamicSetting = Key("dynamicSetting", default: "value") } // Add to iCloud sync later Defaults.iCloud.add(.dynamicSetting) // Remove from iCloud sync Defaults.iCloud.remove(.dynamicSetting) // Remove all keys from iCloud sync Defaults.iCloud.removeAll() // Enable debug logging Defaults.iCloud.isDebug = true ``` -------------------------------- ### Persist Custom Collections Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Implement Defaults.CollectionSerializable to allow custom collection types to be stored in Defaults. ```swift struct Bag: Collection { var items: [Element] var startIndex: Int { items.startIndex } var endIndex: Int { items.endIndex } mutating func insert(element: Element, at index: Int) { items.insert(element, at: index) } func index(after index: Int) -> Int { items.index(after: index) } subscript(position: Int) -> Element { items[position] } } extension Bag: Defaults.CollectionSerializable { init(_ elements: [Element]) { self.items = elements } } extension Defaults.Keys { static let stringBag = Key>("stringBag", default: Bag(["Hello", "World!"])) } Defaults[.stringBag][0] //=> "Hello" Defaults[.stringBag][1] //=> "World!" ``` -------------------------------- ### Defaults.Toggle Component for SwiftUI Source: https://context7.com/sindresorhus/defaults/llms.txt A convenience SwiftUI Toggle component that directly binds to a Defaults key. It supports an `inverted` parameter to store the opposite of the displayed value. ```swift import SwiftUI import Defaults extension Defaults.Keys { static let showAllDayEvents = Key("showAllDayEvents", default: false) static let enableNotifications = Key("enableNotifications", default: true) } struct PreferencesView: View { var body: some View { Form { Defaults.Toggle("Show All-Day Events", key: .showAllDayEvents) .onChange { print("All-day events toggled: \($0)") } Defaults.Toggle("Enable Notifications", key: .enableNotifications) // Inverted toggle - stored value is opposite of displayed Defaults.Toggle("Hide Completed Tasks", key: .showCompleted, inverted: true) } } } ``` -------------------------------- ### Store Enums with Raw Value using PreferRawRepresentable Source: https://context7.com/sindresorhus/defaults/llms.txt Enums with raw values can be stored efficiently using `PreferRawRepresentable`. This is an alternative to the default Codable storage. ```swift import Defaults // Using Codable (default) - stores as JSON string enum Status: String, Codable, Defaults.Serializable { case active case inactive case pending } // Using RawRepresentable - stores raw value directly enum Priority: Int, Defaults.Serializable, Defaults.PreferRawRepresentable { case low = 0 case medium = 1 case high = 2 } extension Defaults.Keys { static let status = Key("status", default: .pending) static let priority = Key("priority", default: .medium) } Defaults[.status] = .active Defaults[.priority] = .high ``` -------------------------------- ### Declare a key with a dynamic default value Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Specify a dynamic default value, useful when the default may change during the app's lifetime. Note that dynamic defaults are not registered in `UserDefaults`. ```swift extension Defaults.Keys { static let camera = Key("camera") { .default(for: .video) } } ``` -------------------------------- ### Set Algebra Types for Defaults Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Implements SetAlgebra for custom SetBag type to be used with Defaults.Serializable. Requires Element to be Serializable and Hashable. ```swift struct SetBag: SetAlgebra { var store = Set() init() {} init(_ store: Set) { self.store = store } func contains(_ member: Element) -> Bool { store.contains(member) } func union(_ other: SetBag) -> SetBag { SetBag(store.union(other.store)) } func intersection(_ other: SetBag) -> SetBag { var setBag = SetBag() setBag.store = store.intersection(other.store) return setBag } func symmetricDifference(_ other: SetBag) -> SetBag { var setBag = SetBag() setBag.store = store.symmetricDifference(other.store) return setBag } @discardableResult mutating func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element) { store.insert(newMember) } mutating func remove(_ member: Element) -> Element? { store.remove(member) } mutating func update(with newMember: Element) -> Element? { store.update(with: newMember) } mutating func formUnion(_ other: SetBag) { store.formUnion(other.store) } mutating func formSymmetricDifference(_ other: SetBag) { store.formSymmetricDifference(other.store) } mutating func formIntersection(_ other: SetBag) { store.formIntersection(other.store) } } extension SetBag: Defaults.SetAlgebraSerializable { func toArray() -> [Element] { Array(store) } } extension Defaults.Keys { static let stringSet = Key>("stringSet", default: SetBag(["Hello", "World!"])) } Defaults[.stringSet].contains("Hello") //=> true Defaults[.stringSet].contains("World!") //=> true ``` -------------------------------- ### Access Defaults Values Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Documentation.md Read and write values using a type-safe subscript on the Defaults object. ```swift Defaults[.quality] //=> 0.8 Defaults[.quality] = 0.5 //=> 0.5 ``` -------------------------------- ### Control change propagation during updates Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/Introduction.md Use `Defaults.withoutPropagation(_:)` to prevent changes within a closure from being propagated to observation callbacks, useful for avoiding infinite recursion. ```swift let observer = Defaults.observe(keys: .key1, .key2) { // … Defaults.withoutPropagation { // Update `.key1` without propagating the change to listeners. Defaults[.key1] = 11 } // This will be propagated. Defaults[.someKey] = true } ``` -------------------------------- ### Check if a Key's Value Equals its Default Source: https://context7.com/sindresorhus/defaults/llms.txt You can check if a key's current value matches its default value directly on the key itself or within SwiftUI using the `@Default` property wrapper. ```swift import Defaults extension Defaults.Keys { static let volume = Key("volume", default: 0.5) } // On the key itself print(Defaults.Keys.volume.isDefaultValue) // => true (if not modified) Defaults[.volume] = 0.8 print(Defaults.Keys.volume.isDefaultValue) // => false ``` ```swift import Defaults import SwiftUI struct VolumeView: View { @Default(.volume) var volume var body: some View { VStack { Slider(value: $volume, in: 0...1) if !_volume.isDefaultValue { Button("Reset to Default") { _volume.reset() } } } } } ``` -------------------------------- ### Use @Default Property Wrapper in SwiftUI Views Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/SwiftUIIntegration.md Use the `@Default` property wrapper to bind a SwiftUI view's state to a Defaults key. This automatically updates the view when the value changes, similar to `@State`. Ensure `@Default` is used within a `View`, not an `ObservableObject`. ```swift extension Defaults.Keys { static let hasUnicorn = Key("hasUnicorn", default: false) } struct ContentView: View { @Default(.hasUnicorn) var hasUnicorn var body: some View { Text("Has Unicorn: \(hasUnicorn)") Toggle("Toggle", isOn: $hasUnicorn) Button("Reset") { _hasUnicorn.reset() } } } ``` -------------------------------- ### Override Preferred Bridge Source: https://github.com/sindresorhus/defaults/blob/main/Sources/Defaults/Documentation.docc/AdvancedUsage.md Use protocols like PreferRawRepresentable to override the default Codable serialization behavior. ```swift enum Mime: String, Codable, Defaults.Serializable, Defaults.PreferRawRepresentable { case json = "application/json" } extension Defaults.Keys { static let mime = Key("mime", default: .json) } print(UserDefaults.standard.string(forKey: "mime")) //=> "application/json" (raw value, not JSON string) ``` -------------------------------- ### Preventing Observation Propagation Source: https://context7.com/sindresorhus/defaults/llms.txt Use withoutPropagation to modify values inside an observer block without triggering the observer again, avoiding infinite recursion. ```swift import Defaults extension Defaults.Keys { static let counter = Key("counter", default: 0) static let lastUpdate = Key("lastUpdate") } let observer = Defaults.observe(keys: .counter, .lastUpdate) { print("Settings changed") // This update won't trigger the observer again Defaults.withoutPropagation { Defaults[.lastUpdate] = Date() } // This will trigger the observer // Defaults[.counter] += 1 // Would cause infinite loop! } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.