Choosing the Right Bad Option
For those of you who aren’t at least knee deep in the world of Objective-C and Cocoa, Key Value Observation (KVO for short) is a technique for directly observing values for changes, and Notifications are broadcast messages sent out by objects on specific events, and with some related information.
Despite the fact that some of the latest cool toys like Reactive Cocoa bieng built atop KVO, and Raizlabs has made some great tools to make it less dangerous, I still don’t really trust it. Which seems to put me in the minority.
More specifically, I can’t always trust it to work so I find it mentally taxing.
With classes that I’ve created, it’s great. Once I’m observing values on classes that I haven’t directly created I need to dig in and check to see if the values are KVO compliant. When it works correctly it’s pretty magical and cuts down on a lot of code.
Notifications on the other hand, are explicitly defined. The biggest issues that I’ve had with notifications are the lack of type safety, which is just plain everywhere in Objective-C, and is magnified with NSNotification by the fact they can include a dictionary of additional values. The other big problem is that they can end up feeling like you’re trying to take a tiny sip from a firehose with all of the notifications flying around inside the app.
That being said, I prefer notifications for anything loosely coupled. Particularly I’ve used them to great effect when building my network stack because it means views can listen for updates from sections of the API that they care about rather than having to listen for callbacks from a particular fetch request. The fact that iOS9 will be adding automatic cleanup for
NSNotification listeners also promises to make working with notifications a little less dangerous.
So Which One’s Better?
The answer is: “It depends”. With your own model objects designed with KVO in mind, KVO is great if you’re using support libraries. With other people’s classes, the answer is check the documentation to see what’s the preferred option. For instance don’t observe the
text property of a
NSTextField, listen for the
UITextFieldTextDidChangeNotification. Stay on the officially supported path where you can, it’s at least slightly less likely to break in a software update.
On Swift and KVO
Pure Swift objects won’t support the under the hood techniques that make KVO work. Instead Swift supports
didSet: on properties, and you’d have to subclass to add in the behaviors if you want to observe a class that you didn’t create to begin with. It’s less flexible, but safer and you get strongly typed values.