Я пытаюсь реализовать класс UserDefaults, используя @propertyWrapper
. Я пытаюсь создать класс-оболочку для предпочтений пользователя моего приложения. Итак, я написал следующий код.
@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)
}
}
}
Затем я хотел бы наблюдать за изменениями значений UserDefaults. Итак, я реализовал класс наблюдения с именем DefaultsObservation
.
class DefaultsObservation: NSObject {
let key: String
private var onChange: (Any, Any) -> Void
init(key: String, onChange: @escaping (Any, Any) -> Void) {
self.onChange = onChange
self.key = key
super.init()
UserDefaults.standard.addObserver(self, forKeyPath: key, options: [.old, .new], context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
guard let change = change, object != nil, keyPath == key else { return }
onChange(change[.oldKey] as Any, change[.newKey] as Any)
}
deinit {
UserDefaults.standard.removeObserver(self, forKeyPath: key, context: nil)
}
}
Также следует мой класс AppData.
struct AppData {
@Storage(key: "layout_key", defaultValue: "list")
static var layout: String
}
Однако, когда я пытался добавить и прослушать изменения, свойство layout
он не работает должным образом.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
AppData.$layout.observe { old, new in
print(old)
}
}
Когда я его отлаживал, deinit
работает, как только вызывается метод viewWillAppear
. Когда я закомментировал deinit
метод удаления наблюдателя, все работает отлично. Думаю, закрытие deinit
может вызвать проблемы с памятью. Так что я не хочу это комментировать. Что мне не хватает и как это решить?