My questionwas about if it was possible to use KVC on a Singleton property on Swift. I was testing KVC on a class was able to get it working but decided to see if it work on a Singleton class.
I'm running into an error stating that the "shared" property of my Singleton isn't KVC-compliant.
class KVOObject: NSObject {
@objc static let shared = KVOObject()
private override init(){}
@objc dynamic var fontSize = 18
}
override func viewDidLoad() {
super.viewDidLoad()
addObserver(self, forKeyPath: #keyPath(KVOObject.shared.fontSize), options: [.old, .new], context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == #keyPath(KVOObject.shared.fontSize) {
// do something
}
}
I am currently getting the error below:
NetworkCollectionTest[9714:452848] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ addObserver: forKeyPath:@"shared.fontSize" options:3 context:0x0] was sent to an object that is not KVC-compliant for the "shared" property.'
The key path is not correct. It’s
KVOObject.fontSize. And you need to add the observer to that singleton:As an aside, (a) you should probably use a context to identify whether you're handling this or whether it might be used by the superclass; (b) you should call the
superimplementation if it's not yours; and (c) make sure to remove the observer ondeinit:Or, if in Swift 4, it's now much easier as it's closure-based (avoiding need for context) and is automatically removed when the
NSKeyValueObservationfalls out of scope:By the way, a few observations on the singleton:
The
sharedproperty does not require@objcqualifier; only the property being observed needs that; andThe
initmethod really should be callingsuper; andI'd probably also declare it to be
finalto avoid confusion that can result in subclassing singletons.Thus: