开发者社区> 问答> 正文

UserDefault属性包装器不保存IOS版本低于IOS 13的值

我使用属性包装来保存我的用户默认值。在iOS 13设备上,这种解决方案非常有效。但是,在IOS 11和IOS 12上,这些值不会保存到用户默认值中。我读到属性包装是向后兼容的,所以我不知道为什么在较旧的IOS版本上不能这样做。

这是属性包装器:

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

    init(key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    var wrappedValue: T {
        get {
            guard let data = UserDefaults.standard.object(forKey: key) as? Data else {
                // Return defaultValue when no data in UserDefaults
                return defaultValue
            }

            // Convert data to the desire data type
            let value = try? JSONDecoder().decode(T.self, from: data)
            return value ?? defaultValue
        }
        set {
            // Convert newValue to data
            let data = try? JSONEncoder().encode(newValue)

            UserDefaults.standard.set(data, forKey: key)
            UserDefaults.standard.synchronize()
        }
    }
}

struct UserDefault {
    @UserDefaultWrapper(key: "userIsSignedIn", defaultValue: false)
    static var isSignedIn: Bool
}

然后,我可以这样设置

UserDefault.isSignedIn = true

我是不是用错了属性包装器?是否还有其他人在较早的IOS版本上遇到属性包装的问题?

展开
收起
游客5akardh5cojhg 2019-12-25 16:25:11 4615 0
1 条回答
写回答
取消 提交回答
  • 与财产包装无关!问题是,在IOS 12和之前,一个简单的值,比如bool,虽然可以编码为财产可编码结构(例如),则不能。本身被编码。错误(您正在丢弃的)非常清楚这一点:

    顶级Bool编码为编号JSON片段。

    因此,例如,如果我们将示例更改为:

    struct UserDefault { @UserDefaultWrapper(key: "userIsSignedIn", defaultValue: Person(firstName:"Matt")) static var isSignedIn: Person }

    struct Person : Codable { let firstName : String } 我们在发射时说

    print(UserDefault.isSignedIn) UserDefault.isSignedIn = Person(firstName:"Charlotte") 我们在连续发射时得到了正确的答案。

    这一事实说明了一个解决方案。重新定义属性包装器,如下所示:

    struct UserDefaultWrapper<T: Codable> { struct Wrapper : Codable where T : Codable { let wrapped : T }

    private let key: String
    private let defaultValue: T
    
    init(key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }
    
    var wrappedValue: T {
        get {
            guard let data = UserDefaults.standard.object(forKey: key) as? Data 
                else { return defaultValue }
            let value = try? JSONDecoder().decode(Wrapper<T>.self, from: data)
            return value?.wrapped ?? defaultValue
        }
        set {
            do {
                let data = try JSONEncoder().encode(Wrapper(wrapped:newValue))
                UserDefaults.standard.set(data, forKey: key)
            } catch {
                print(error)
            }
        }
    }
    

    } 现在它可以在iOS 12上工作了。和IOS 13。

    2019-12-25 16:25:30
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
手淘iOS性能优化探索 立即下载
From Java/Android to Swift iOS 立即下载
深入剖析iOS性能优化 立即下载