I have recently stumbled upon a recipe for UserDefaults
that greatly improves its usability with observe
. However, it only works well when the type of the custom property and the type of the underlying value match:
import Foundation
extension UserDefaults {
@objc dynamic var int: Int {
get {
return integer(forKey: "int")
}
set {
set(newValue, forKey: "int")
}
}
}
let defaults = UserDefaults.standard
defaults.int = 1
let o1 = defaults.observe(\.int, options: [.initial, .old, .new]) { (_, change) in
print("int: \(change.oldValue) -> \(change.newValue)")
}
defaults.int = 2
produces
int: nil -> Optional(1)
int: Optional(1) -> Optional(2)
int: Optional(1) -> Optional(2)
But when there is a mismatch (Int
vs String
in this case):
extension UserDefaults {
@objc dynamic var intString: String {
get {
return String(integer(forKey: "intString"))
}
set {
set(Int(newValue), forKey: "intString")
}
}
}
defaults.intString = "1"
let o2 = defaults.observe(\.intString, options: [.initial, .old, .new]) { ( _ , change) in
print("intString: \(change.oldValue) -> \(change.newValue)")
}
defaults.intString = "2"
it produces
intString: nil -> nil
intString: nil -> nil
intString: nil -> nil
My questions are:
- Is this a legitimate approach?
- If so, is the behavior when types mismatch intentional or error-prone?