我正在为 UserDefaults
创建一个属性包装器。
我想要实现的是:
- 为属性设置非零值会将其存储在用户默认值中。
- 设置 nil 将从 UserDefault 中删除该对象。
但是下面的代码会引发编译器错误:
Initializer for conditional binding must have Optional type, not 'T'
@propertyWrapper
struct UserDefault<T> {
let key: String
let defaultValue: T
init(_ key: String, defaultValue: T) {
self.key = key
self.defaultValue = defaultValue
}
var wrappedValue: T {
get { UserDefaults.standard.value(forKey: key) as? T ?? defaultValue }
set {
if let newValue = newValue {
UserDefaults.standard.setValue(newValue, forKey: key)
} else {
UserDefaults.standard.removeObject(forKey: key)
}
}
}
}
// Declaration
@UserDefault("key", defaultValue: nil)
static var newUserDefaultValue: String
有什么方法可以判断T是可选的吗?因为我可以从 UserDefaults 中删除 key 。如果不是如何达到预期的输出?
最佳答案
您的代码中有两个问题:
1) 在您的情况下,wrappedValue
和 defaultValue
应该是可选的:
struct UserDefault<T> {
let key: String
let defaultValue: T? // defaultValue should be optional
// defaultValue should be optional
init(_ key: String, defaultValue: T?) {
self.key = key
self.defaultValue = defaultValue
}
// wrappedValue should also be optional
var wrappedValue: T? {
get { UserDefaults.standard.value(forKey: key) as? T ?? defaultValue }
set {
if let newValue = newValue {
UserDefaults.standard.setValue(newValue, forKey: key)
} else {
UserDefaults.standard.removeObject(forKey: key)
}
}
}
}
2) 如果使用 nil defaultValue
进行初始化,则应为编译器指定类型 T
:
// Type T should be expicitly specified. For example as String
let valueWithNilDefault = UserDefault<String>("key", defaultValue: nil)
// Type T will be determined during compile time as Int
let valueWithDefault = UserDefault("key", defaultValue: 15)
关于ios - 如何检测类型对于通用 propertyWrapper 是可选的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58802347/