如何解决如何使用 UserDefaults propertyWrapper 无缝包装 @Published 变量
我一直在寻找完美的 UserDefaults 包装器
- 对存储中的数据对象进行无缝编码和解码
- 与@Published 合作
我的起点是这个 StackOverflow answer,但它使用了 object:forKey
,它不适用于自定义对象(编码 URL 对我来说总是很重要)。
我的想法是能够像这样使用它:
struct Server: Identifiable,Codable,Equatable,Hashable { /* vars */ }
class ServerPickerviewmodel: ObservableObject {
@Published(wrappedValue: Server.defaultServers.first!,type: Server.self,key: "currentServer")
var currentServer: Server?
}
为了实现这一点,我修改了@VictorKushnerov 的回答中的代码:
import Combine
private var cancellables = [String: AnyCancellable]()
extension Published {
init<T: encodable & Decodable>(wrappedValue defaultValue: T,type: T.Type,key: String) {
let decoder = JSONDecoder()
var value: T
if
let data = UserDefaults.standard.data(forKey: key),let decodedVal = try? decoder.decode(T.self,from: data) {
value = decodedVal
} else {
value = defaultValue
}
self.init(initialValue: value) // <-- Error
cancellables[key] = projectedValue.sink { val in
let encoder = JSONEncoder()
let encodedVal = encoder.encode(val) // <-- Error
UserDefaults.standard.set(encodedVal,forKey: key)
}
}
}
-
Cannot convert value of type 'T' to expected argument type 'Value'
它仍然依赖底层@Published
的Value
泛型类型,我希望我可以用我的类型 T 覆盖它。 Instance method 'encode' requires that 'Published<Value>.Publisher.Output' (aka 'Value') conform to 'encodable'
解决方法
您可以通过使用 where Value : Codable
来限制您的扩展来修复编译错误。然后,您可以完全摆脱 T
泛型(并且您也不必使用 type
参数):
extension Published where Value : Codable {
init(wrappedValue defaultValue: Value,key: String) {
let decoder = JSONDecoder()
var value: Value
if
let data = UserDefaults.standard.data(forKey: key),let decodedVal = try? decoder.decode(Value.self,from: data) {
value = decodedVal
} else {
value = defaultValue
}
self.init(initialValue: value)
cancellables[key] = projectedValue.sink { val in
let encoder = JSONEncoder()
do {
let encodedVal = try encoder.encode(val)
UserDefaults.standard.set(encodedVal,forKey: key)
} catch {
print(error)
assertionFailure(error.localizedDescription)
}
}
}
}
话虽如此,我可能会采用路径而不是创建自定义属性包装器来包装 @AppStorage
而不是扩展 @Published
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。