SwiftyUserDefaults

repository·master·Indexed 26 days ago

https://github.com/sunshinejr/swiftyuserdefaults

A modern, type-safe Swift API for interacting with NSUserDefaults. It provides a centralized way to define keys using DefaultsKey, supports Codable, NSCoding, and RawRepresentable types via DefaultsSerializable, and offers a @SwiftyUserDefault property wrapper for Swift 5.1+. Features include KVO observation, dynamic member lookup for key path access, and support for using launch arguments as typed values.

Tokens
4.1K
Snippets
16
Records
20
Agent score
89%

What's inside SwiftyUserDefaults

  1. Migrate DefaultsBridge implementation from 4.x to 5.x

    master

    In version 5.x, DefaultsBridge has changed from a class to a struct.

    Key changes for implementers:

    1. Composition over Inheritance: Since it is now a struct, you can no longer use inheritance to reuse bridge logic; you must use composition instead.
    2. Removal of isSerializable: The isSerializable property has been removed. You can safely delete this property from your implementation.
    3. Mandatory deserialize(): When implementing a custom bridge, you must always provide a deserialize() method.
  2. Migrate Defaults access syntax from 4.x to 5.x

    master

    In version 5.x, Defaults is a global DefaultsAdapter object rather than a UserDefaults typealias. This change enables key path access and dynamic access.

    If you were using key paths, switch from subscripting with a dot to using the key path syntax:

    • Old (4.x): Defaults[.yourKey]
    • New (5.x): Defaults[\.yourKey] or Defaults.yourKey (if using Swift 5.1+)

    If you are accessing a key using a DefaultsKey object directly, you must now use the explicit key: argument label:

    • Old (4.x): Defaults[key]
    • New (5.x): Defaults[key: key]
  3. Migrate DefaultsKeys definitions from 4.x to 5.x

    master

    In version 5.x, DefaultsKeys is a default object conforming to DefaultsKeyStore that is passed to the global Defaults. Instead of defining keys as static let properties, you must now define them as computed properties within an extension of DefaultsKeys.

    • Old (4.x): static let userThemeName = DefaultsKey<String?>("userThemeName")
    • New (5.x): var userThemeName: DefaultsKey<String?> { .init("userThemeName") }
    extension DefaultsKeys {
        var userThemeName: DefaultsKey<String?> { .init("userThemeName") }
    }
  4. Define user defaults keys using DefaultsKey

    master

    To use SwiftyUserDefaults, you must first define your keys. Create a DefaultsKey object by specifying the type in angle brackets, the key name in parentheses, and an optional defaultValue for non-optional types.

    You can then access these keys using the Defaults subscript with the key: argument.

    let colorKey = DefaultsKey<String>("color", defaultValue: "")
    
    Defaults[key: colorKey] = "red"
    let color = Defaults[key: colorKey] // => "red", typed as String
  5. Install SwiftyUserDefaults

    master

    You can install SwiftyUserDefaults using CocoaPods, Carthage, or Swift Package Manager.

    Requirements:

    • Swift >= 4.1
    • iOS >= 9.0
    • macOS >= 10.11
    • tvOS >= 9.0
    • watchOS >= 2.0
    ### CocoaPods
    
    Add to Podfile:
    ```ruby
    pod 'SwiftyUserDefaults', '~> 5.0'

    Run:

    pod install

    Carthage

    Add to Cartfile:

    github "sunshinejr/SwiftyUserDefaults" ~> 5.0

    Swift Package Manager

    Add to Package.swift:

    let package = Package(
        name: "MyPackage",
        products: [...],
        dependencies: [
            .package(url: "https://github.com/sunshinejr/SwiftyUserDefaults.git", .upToNextMajor(from: "5.0.0"))
        ],
        targets: [...]
    )
  6. Use Launch Arguments as UserDefaults

    master

    SwiftyUserDefaults supports using command line or launch arguments as statically typed values. Currently supported types are Bool, Double, Int, and String.

    // In XCUIApplication tests
    func testExample() {
        let app = XCUIApplication()
        app.launchArguments = ["-skipLogin", "true", "-loginTries", "3", "-lastGameTime", "61.3", "-nickname", "sunshinejr"]
        app.launch()
    }
    
    // Via Command Line
    ./script -skipLogin true -loginTries 3 -lastGameTime 61.3 -nickname sunshinejr
  7. Define keys using DefaultsKeys extension for dot syntax

    master

    For a more expressive API, extend the DefaultsKeys class with static properties. This allows you to use the Defaults[\.keyName] shortcut syntax, which provides compile-time safety and convenient access.

    extension DefaultsKeys {
        var username: DefaultsKey<String?> { .init("username") }
        var launchCount: DefaultsKey<Int> { .init("launchCount", defaultValue: 0) }
    }
    
    // Usage
    Defaults[\.username] = "joe"
    Defaults[\.launchCount] += 1
  8. Migrate from legacy String keys to DefaultsKey

    master

    In version 4.0 and later, support for using String values directly as keys was removed. You must migrate to using DefaultsKey to benefit from static typing. If you previously used Any as a type for DefaultsKey, you must now specify a concrete, proper type.

    // Old way (removed in v4)
    let value = Defaults["key"].intValue
    
    // New way
    let key = DefaultsKey<Int>("key")
    let value = Defaults[key]
  9. Extend existing types with DefaultsSerializable

    master

    If a type already conforms to NSCoding, Codable, or RawRepresentable (like UIColor), you can make it compatible with SwiftyUserDefaults by simply adding a DefaultsSerializable conformance extension.

    extension UIColor: DefaultsSerializable {}
  10. Access defaults via KeyPath dynamicMemberLookup

    master

    If you define keys in a DefaultsKeys extension, you can access them directly via the Defaults singleton using dynamic member lookup. This allows for concise getting, setting, and in-place modification of values (including arrays and custom types).

    extension DefaultsKeys {
        var username: DefaultsKey<String?> { .init("username") }
        var launchCount: DefaultsKey<Int> { .init("launchCount", defaultValue: 0) }
    }
    
    // Get and set
    let username = Defaults.username
    Defaults.hotkeyEnabled = true
    
    // Modify in place
    Defaults.launchCount += 1
    Defaults.volume -= 0.1
    
    // Modify arrays
    Defaults.libraries.append("SwiftyUserDefaults")
    Defaults.libraries[0] += " 2.0"
  11. Observe UserDefaults changes with KVO

    master

    You can observe changes to DefaultsKey values using Defaults.observe. This works for all types that are DefaultsSerializable.

    Available observation options include:

    • .initial: Trigger the observer immediately with the current value.
    • .old: Provide the previous value.
    • .new: Provide the new value.

    By default, Defaults.observe uses [.old, .new].