UserDefaults 宏

Swift

此仓库提供了一些宏,以帮助减少使用 UserDefaults 存储值的样板代码。

为什么使用这个宏?

开始使用

添加到你的项目

将对此仓库的引用添加到你的项目。如果使用 SwiftPM,你可以使用以下模板;否则,你可以在 Xcode 中搜索此仓库。

dependencies: [
    .package(url: "https://github.com/maniramezan/UserDefaultMacro.git", .upToNextMajor(from: "1.0.0")),
],

此包包含三个宏,其中两个宏旨在协同工作

UserDefaultDataStore

这是一个高级宏,旨在通常用于 structclass 类型

@UserDefaultDataStore
struct UserDefaultsStore {
}

此宏将以下代码添加到其附加的任何实体

  1. 创建 userDefaults 属性
  2. 创建 init(userDefaults:) 方法
@UserDefaultDataStore
struct UserDefaultsStore {
    // START: Added by UserDefaultDataStore
    private let userDefaults: UserDefaults

    internal init(userDefaults: UserDefaults = .standard) {
        self.userDefaults = userDefaults
    }
    // END
}

此外,此宏将任何可变变量标记为 @UserDefaultRecord。这会将这些变量扩展为计算变量,这些计算变量在内部使用上面定义的 userDefaults 属性来存储它们的值。

@UserDefaultDataStore
struct UserDefaultsStore {
    // START: Added by UserDefaultDataStore
    @UserDefaultRecord
    // END
    var isFirstTimeLaunching: Bool
    // START: Added by UserDefaultRecord
    {
        get {
            userDefaults.bool(forKey: "isFirstTimeLaunching")
        }
        set {
            userDefaults.set(newValue, forKey: "isFirstTimeLaunching")
        }
    }
    // END

    // ...
}

@UserDefaultDataStore 宏默认为 internal 用于 init(userDefaults:) 方法。此外,UserDefaults.standard 用作 userDefaults 属性的默认值。你可以通过将参数传递给宏来更改这些默认值

extension UserDefaults {
    static let test = UserDefaults(suiteName: "test")!
}

@UserDefaultDataStore(using: .test, accessLevel: .public)
struct UserDefaultsStore {
    private let userDefaults: UserDefaults

    public init(userDefaults: UserDefaults = .test) {
        self.userDefaults = userDefaults
    }
}

@UserDefaultRecord 宏也是如此。你可以传递自定义键和默认值给它

@UserDefaultDataStore(using: .test, accessLevel: .public)
struct UserDefaultsStore {
    @UserDefaultRecord(key: "isInitialLaunch", defaultValue: true)
    var isFirstTimeLaunching: Bool
    {
        get {
            userDefaults.bool(forKey: "isInitialLaunch")
        }

        set {
            userDefaults.setValue(newValue, forKey: "isInitialLaunch")
        }
    }

    private let userDefaults: UserDefaults

    public init(userDefaults: UserDefaults = .test) {
        self.userDefaults = userDefaults
        userDefaults.register(defaults: ["isInitialLaunch": true])
    }
}

请注意,添加 defaultValue 也会修改 init(userDefaults:) 方法,以便为实体注册默认值。

UserDefaultProperty

不建议使用此宏,并且可能会在未来的版本中根据反馈将其删除。这与 @UserDefaultRecord 宏非常相似,但它可以独立使用。你可以传递 UserDefaultskeydefaultValue 来自定义生成的计算属性,或者直接使用它而不带任何参数

extension UserDefaults {
    static let test = UserDefaults(suiteName: "test")!
}

struct SomeEntity {
    static let key = "customized_key"
    @UserDefaultProperty(using: .test, key: Self.key, defaultValue: "Some default value")
    var randomGeneratedString: String
    {
        get {
            UserDefaults.test.register(defaults: [Self.key: "Some default value"])
            return UserDefaults.test.string(forKey: Self.key)!
        }

        set {
            UserDefaults.test.setValue(newValue, forKey: Self.key)
        }
    }
}

请注意,由于这也支持默认值,因此生成的计算属性包括在 getter 中注册默认值。这确保了默认值始终在从 UserDefaults 中获取之前注册。

联系方式

如果您有任何问题、功能请求或错误报告,请随时使用仓库中的 Issues 或在 Twitter 上联系我 @maniramezan

贡献

如果您有任何改进此仓库的想法,请随时 fork 并发送 pull request。我将非常乐意审查并合并它。

许可

此仓库根据 MIT 许可证获得许可。有关更多信息,请参阅 LICENSE

参考

非常感谢 Jesse Squires,感谢他撰写了关于编写更好的 @UserDefault 属性包装器的精彩文章。