ios - 具有通用(可选)用户默认值的属性包装器
问题描述
适当参考:
我们已经开始为 UserDefaults 使用属性包装器,它可以与非可选属性无缝协作。
但是,设置 nil 的可选属性会崩溃:
[用户默认值] 尝试将非属性列表对象设置为键“someKeyThatWeSet”的 NSUserDefaults/CFPreferences 值
由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“尝试为键“someKeyThatWeSet”插入非属性列表对象 null
下面的代码可以直接在 Playground 上测试:
@propertyWrapper
struct C2AppProperty<T> {
let key: String
let defaultValue: T
init(_ key: String, defaultValue: T) {
self.key = key
self.defaultValue = defaultValue
}
var wrappedValue: T {
get {
return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
}
set {
UserDefaults.standard.set(newValue, forKey: key)
}
}
}
struct C2User {
@C2AppProperty("userID", defaultValue: nil)
public static var publicUserID: String?
}
print(C2User.publicUserID)
C2User.publicUserID = "edusta"
print(C2User.publicUserID)
C2User.publicUserID = nil
print(C2User.publicUserID)
预期的:
零
可选<"edusta">
零
成立:
零
可选<"edusta">
libc++abi.dylib:以 NSException 类型的未捕获异常终止
到目前为止我已经尝试过:
set {
// Comparing non-optional value of type 'T' to nil always returns false.
if newValue == nil {
UserDefaults.standard.removeObject(forKey: combinedKey)
} else {
UserDefaults.standard.set(newValue, forKey: combinedKey)
}
}
这里需要什么样的检查才能捕捉到 newValue 是nil
什么?还是一个Optional<nil>
?
解决方案
这段代码对我有用:
@propertyWrapper
struct UserDefault<T> {
private let key: String
private let defaultValue: T
private let userDefaults: UserDefaults
init(_ key: String, defaultValue: T, userDefaults: UserDefaults = .standard) {
self.key = key
self.defaultValue = defaultValue
self.userDefaults = userDefaults
}
var wrappedValue: T {
get {
guard let value = userDefaults.object(forKey: key) else {
return defaultValue
}
return value as? T ?? defaultValue
}
set {
if let value = newValue as? OptionalProtocol, value.isNil() {
userDefaults.removeObject(forKey: key)
} else {
userDefaults.set(newValue, forKey: key)
}
}
}
}
fileprivate protocol OptionalProtocol {
func isNil() -> Bool
}
extension Optional : OptionalProtocol {
func isNil() -> Bool {
return self == nil
}
}
推荐阅读
- php - CodeIgniter 4 模型预加载
- python - 密码生成器中的 if 语句问题
- javascript - 如何在键盘打开时隐藏浮动按钮(Android/iOS)?
- ruby-on-rails - 如何在 Jenkinsfile 中配置 Jenkins 中 Rails 应用程序的测试套件使用的数据库?
- excel - Excel 搜索范围,带回行内容
- html - 控制嵌套网格布局中的图像大小
- c# - 无法链接\导入来自不同文件夹的原始文件
- python - 如何使用内置的 python 模块创建垂直直方图?
- python - Pandas 按条件分组
- variables - 如何在 Qlik Sense 中为具有多个字段的饼图编写变量