Re: wasting space?
Re: wasting space?
- Subject: Re: wasting space?
- From: "Michael Ash" <email@hidden>
- Date: Mon, 6 Oct 2008 14:05:13 -0400
On Mon, Oct 6, 2008 at 11:56 AM, I. Savant <email@hidden> wrote:
> On Sun, Oct 5, 2008 at 4:13 PM, Michael Ash <email@hidden> wrote:
>
>> KVO is terribly, horribly, frighteningly flawed at the API level but it
>> can still be very handy once you know the Magic Incantation.
>
> You just *know* that when you make such a blanket statement, some
> smart-ass is going to ask you to cite specific examples. I would be
> honored if you'd consider me that smart-ass. :-)
I thought it was obvious!
But seriously.... The problem is fairly simple to explain, but I think
the impact is best illustrated with an example that compares it to
what I consider to be a good API, such as NSNotificationCenter. Here's
how you respond to several different notifications with
NSNotificationCenter:
- (void)someObjectDidSomething:(NSNotification *)note {
...
}
- (void)someObjectDidSomethingElse:(NSNotification *)note {
...
}
- (void)anotherObjectDidSomething:(NSNotification *)note {
...
}
And then here's how you do the equivalent thing with KVO:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if(context == kMyMagicGuaranteedUniqueContextPointer) {
if(object == someObject) {
if([keyPath isEqualToString:@"something"]) {
...
}
else if([keyPath isEqualToString:@"somethingElse"]) {
...
}
}
else if(object == anotherObject) {
...
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];
}
}
Key problems with the second one:
- The kMyMagicGuaranteedUniqueContextPointer constant has to be
generated in the right way, and the only way you can really use this
context parameter is the way this method does, purely to decide
whether the message is meant for you or for your superclass. You
can't, say, pass a handy value in it to help you with your processing.
- You have to manually compare the object and the key path against the
ones you're interested in to decide what to do.
Basically, KVO ought to ditch the silly context pointer and let you
specify a selector the way NSNotificationCenter does. Any time you
have a long chain of if statements like this it means that you should
probably leverage the language's built-in dispatch mechanisms rather
than rolling your own. NSNotificationCenter does this nicely by
letting you simply tell it what message to send you when something
happens. If you have some kind of generic handler that can deal with a
bunch of different cases, you can just give all those cases the same
selector.
To make things worse, it's really easy to implement this method in the
wrong way and still have it work. Until one day the system ends up
observing something new or making some other such change, and then
your code blows up mysteriously. (It is so easy to implement it in the
wrong way that the documentation makes absolutely no mention that I
can find of the correct way, and the one example in the documentation
is flat-out wrong. As far as I know the only official place where you
can find the correct way to implement it is by auto-completing
"observe" in Xcode.)
It baffles me how the KVO API came to be, given the good examples in
the API that the designers could have followed. I used to assume that
there was some advantage to it that I just hadn't discovered yet, but
after so many years of still not discovering that advantage I'm forced
to conclude that it's simply bad. If I'm wrong, please tell me what it
is!
But like I said, it's not unworkable, and once you know the Magic
Method Structure the rest is relatively straightforward, it's just
really clunky.
Mike
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please 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