KVO, design and documentaion
KVO, design and documentaion
- Subject: KVO, design and documentaion
- From: patrick machielse <email@hidden>
- Date: Thu, 25 Jan 2007 22:44:33 +0100
I've recently been using Key Value Observing, and ran into some
problems. On reflection it turned out that I had become confused by
the superficial (and not so superficial) similarities between KVO and
the Cocoa notifications system (à la NSNotificationCenter). Both are
'notification' mechanisms, both do not retain their observers, and
both even use very similar method names. Where they differ is in how
they handle observer registration...
For notifications it is possible to register for a notification more
than once but still only receive 1 notification:
NotificationCenter:
-------------------
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(test:) name:@"test"
object:object];
[center addObserver:self selector:@selector(test:) name:@"test"
object:object];
The test: method will only be called *once* for each notification
that that is posted. Compare this with KVO:
KVO:
----
[object addObserver:self forKeyPath:@"test" options:0 context:NULL];
[object addObserver:self forKeyPath:@"test" options:0 context:NULL];
self will now get notified *twice* for the exact same change. I'm not
sure how useful this feature is, but I may not have enough
imagination...
When it becomes time to remove the observer the behaviour is also
different between KVO and NSNotificationCenter:
NotificationCenter:
-------------------
[[[NSNotificationCenter defaultCenter] removeObserver:self];
This is a perfectly safe method to call, even if self isn't
registered with the center at all. Contrast this with the equivalent
KVO method:
KVO:
----
[object removeObserver:self forKeyPath:@"test"];
This KVO method will cause a *crash* if self wasn't regitered with
the object in the first place...
To sum up the behaviour of the KVO registration:
1 - addObserver: always adds another notification.
2 - removeObserver: crashes if the observer isn't registered...
3 - there is no API for finding out if an object is registered with
with an object.
This means that in practice you must be extra careful when using KVO.
It adds a memory management like complexity to key value observing.
At the moment I can't really see why it was designed like this, but
if someone has insight into the hows and whys of this implementation
I'd really like to know!
For all I know there may be perfectly good reasons for the current
KVO implementation, but what disappointed me quite a bit while trying
to find out how KVO works is that none of this is discussed in the
documentation. It's not in the KVO programming guide, it's not in the
NSKeyValueObserving Protocol Reference, I couldn't even find it in
'mmalc's Cocoa bindings examples and hints'...
Notice also that I used:
[object addObserver:self forKeyPath:@"test" options:0 context:NULL];
I'm passing 0 for options:, because I'm not interested in either the
new or the old value of the 'test' property. *NOWHERE* in the
documentation does it say that this is allowed or even works. There
also isn't a constant defined for it, which adds to the (my)
confusion. (this is of course an implementation issue, not just one
of documentation)
I don't mean to pick on the KVO documentation in particular
(NSNotificationCenter's docs *also* don't tell you what to expect!),
but since there have been a fair amount of complaints about the
shortcomings of the bindings documentation I expected to find a lot
more details. Bindings and KVO have been with us for three and a half
years now, and I still find myself writing test programs to find out
elementary behaviours...
If it turns out this is in fact written down (somewhere..), I'll
gladly eat my words. (That's one of the advantages e-mail offers over
paper ;-))
patrick_______________________________________________
Cocoa-dev mailing list (email@hidden)
Do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden