Pierre Bernard

My little hideout on the net

Key-Value Observing Done Right. Again.

I love using KVO for all sorts of things: side-effect, flagging UI as dirty, resetting caches, …

Writing the observeValueForKeyPath:ofObject:change:context: method has long since become tedious. So I created a TextExpander snippet to write it for me.

Still, I don't quite like it relying of string comparisons (which I use for context). And I regularly find myself forgetting to unregister observers.

Mike Ash wrote a interesting blog post where he makes a couple of good points against the current KVO API. The most important of which, I think, is the fact unregistering an observer might actually break behavior upon which the superclass relies.

Andy Matuschak has proposed a very convenient API which uses blocks to handle observation callbacks. While I love this solution, I found it to still have a couple of drawbacks:

  • Andy's KVO+Blocks requires Mac OS X Snow Leopard. It relies not only on blocks, but also on associated objects and Grand Central Dispatch.
  • Code is not always easer to read when the callback block is written where it is registered. At times, I would prefer a traget+action setup
  • KVO+Blocks make it all too easy to create retain cycles: referencing an instance variable from within the block retains the owning object.

Inspired by Mike's and Andy's writings and work, I have come up with my own implementation: HHKeyValueObserver.

  • Works on both Leopard and Snow Leopard. Relies on HHAssociatedObjects
  • Target action mechanism with the following signatures: actionWithInfo:change: or actionWithInfo:
  • Uses blocks where available
  • Unregisters automatically on dealloc of the observer

Retain cycles may be avoided by referring to the observed object by the way of observationInfo.observee.