如何在Swift中实现一个通用结构来管理UserDefaults的键值对? [英] How can I implement a generic struct that manages key-value pairs for UserDefaults in Swift?

查看:53
本文介绍了如何在Swift中实现一个通用结构来管理UserDefaults的键值对?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Swift中实现一种管理UserDefaults映射的结构?现在,我具有一些不同类型的计算属性a,b,c,d和对应的键,如下所示:

How would one implement a struct that manages UserDefaults mappings in Swift? Right now I have some computed properties a, b, c, d of different types and corresponding keys that look like this:

enum UserDefaultsKeys {
    a_key
    b_key
    ...
}
var a: String {
    get { UserDefaults.standard.string(forKey: UserDefaultsKeys.a_key.rawValue) }
    set { UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.a_key.rawValue) }
}
var b: Int {
    get { UserDefaults.standard.integer(forKey: UserDefaultsKeys.b_key.rawValue) }
    set { UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.b_key.rawValue) }
}
...

我想实现的是实现一个具有String类型的键和泛型类型值的结构.值get函数应该-根据其类型-选择是否使用 UserDefaults.standard.string UserDefaults.standard.integer ,这样我就可以创建带有某些内容的DefaultsVar密钥,其他所有内容都会自动为我管理.到目前为止,我的情况是这样:

What I would like to achieve instead is to implement a struct that has a key of type String and a generic type value. The value get function should - depending on its type - chose wether to use UserDefaults.standard.string or UserDefaults.standard.integer so that I can just create a DefaultsVar with some key and everything else is managed automatically for me. What I have so far is this:

struct DefaultsVar<T> {
    let key: String
    var value: T {
        get {
            switch self {
                case is String: return UserDefaults.standard.string(forKey: key) as! T
                case is Int: return UserDefaults.standard.integer(forKey: key) as! T
                default: return UserDefaults.standard.float(forKey: key) as! T
            }
        }
        set { UserDefaults.standard.set(newValue, forKey: key) }
    }
}

我收到以下错误:从DefaultsVar转换为不相关的类型'String'总是失败.我是新手(对编程来说是相对较新的),而且并不真正了解如何以正确的方式实现这种方法,或者即使这是一种被认为是一种好的做法,我也不是很了解.有人可以照一下吗?

I get the following error: "Cast from DefaultsVar to unrelated Type 'String' always fails. I am completely new to swift (and relatively new to programming) and don't really understand how to implement this the right way - or if this is even an approach that would be considered a good practice. Could someone please shine some light on this?

提前谢谢!

推荐答案

您可以使用自定义

@propertyWrapper
struct UserDefaultStorage<T: Codable> {
    private let key: String
    private let defaultValue: T

    private let userDefaults: UserDefaults

    init(key: String, default: T, store: UserDefaults = .standard) {
        self.key = key
        self.defaultValue = `default`
        self.userDefaults = store
    }

    var wrappedValue: T {
        get {
            guard let data = userDefaults.data(forKey: key) else {
                return defaultValue
            }
            let value = try? JSONDecoder().decode(T.self, from: data)
            return value ?? defaultValue
        }
        set {
            let data = try? JSONEncoder().encode(newValue)
            userDefaults.set(data, forKey: key)
        }
    }
}

此包装器可以将任何一种可编码的代码存储/恢复到用户默认设置中.

This wrapper can store/restore any kind of codable into/from the user defaults.

@UserDefaultStorage(key: "myCustomKey", default: 0)
var myValue: Int


iOS 14

SwiftUI有一个类似的包装(仅适用于iOS 14),名为 @AppStorage ,它可以用作状态.使用它的好处是它可以直接用作 State .但是它需要 SwiftUI ,并且只能在iOS 14上运行.


iOS 14

SwiftUI has a similar wrapper (only for iOS 14) called @AppStorage and it can be used as a state. The advantage of using this is that it can be used directly as a State. But it requires SwiftUI and it only works from the iOS 14.

这篇关于如何在Swift中实现一个通用结构来管理UserDefaults的键值对?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆