UserDefaults extension for custom keys and observation

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?