Ios 使用PropertyWrapper实现UserDefaults会导致奇怪的问题
我正在尝试使用Ios 使用PropertyWrapper实现UserDefaults会导致奇怪的问题,ios,swift,key-value-observing,property-wrapper,Ios,Swift,Key Value Observing,Property Wrapper,我正在尝试使用@propertyWrapper实现UserDefaults类。我试图做的是为我的应用程序用户首选项创建一个包装器类。所以我写了下面的代码 @propertyWrapper struct Storage<T> { private let key: String private let defaultValue: T var projectedValue: Storage<T> { return self } var wrapp
@propertyWrapper
实现UserDefaults类。我试图做的是为我的应用程序用户首选项创建一个包装器类。所以我写了下面的代码
@propertyWrapper
struct Storage<T> {
private let key: String
private let defaultValue: T
var projectedValue: Storage<T> { return self }
var wrappedValue: T {
get {
return UserDefaults.standard.string(forKey: key) as? T ?? defaultValue
}
set {
UserDefaults.standard.set(newValue, forKey: key)
}
}
init(key: String, defaultValue: T) {
self.key = key
self.defaultValue = defaultValue
}
func observe(change: @escaping (T?, T?) -> Void) -> NSObject {
return DefaultsObservation(key: key) { old, new in
change(old as? T, new as? T)
}
}
}
另外,我的AppData类如下所示
struct AppData {
@Storage(key: "layout_key", defaultValue: "list")
static var layout: String
}
但是,当我尝试添加和侦听更改布局
属性时,它无法正常工作
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
AppData.$layout.observe { old, new in
print(old)
}
}
当我调试它时,deinit
会在调用viewwillbeen
方法时立即工作。当我注释掉去除观察者的方法时,一切都很完美。我认为关闭Denit会导致一些内存问题。所以我不想把它评论掉。我遗漏了什么以及如何解决它?方法观察(更改:@escaping(T?,T?)
初始化DefaultsObservation
对象并返回值。没有对此对象的任何强引用,因此它被解除分配并调用deInit
。您需要保留此对象的强引用。例如
var valueObserver: NSObject? = nil
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
valueObserver = AppData.$layout.observe { old, new in
print(old)
}
}
方法observe(更改:@escaping(T?,T?)
初始化DefaultsObservation
对象并返回值。此对象没有任何强引用,因此它被解除分配并调用deInit
。您需要保留此对象的强引用。例如
var valueObserver: NSObject? = nil
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
valueObserver = AppData.$layout.observe { old, new in
print(old)
}
}
可能是不相关的,但是有一个类型的错误。<代码>字符串(代码:<代码> >用户错误< /COD>总是返回代码>字符串< /代码>(或<代码> nIL/COD>)。要更通用,你必须写<代码>对象(FROKE:字符串(FracK:<代码> > <代码错误> <代码> >始终返回代码>字符串< /代码>(或<代码> nIL/COD>)。为了更通用,您必须编写<代码>对象(FROKE:)谢谢,我认为编写更通用的代码。