Re: KVO and the observeValueForKeyPath bottleneck
Re: KVO and the observeValueForKeyPath bottleneck
- Subject: Re: KVO and the observeValueForKeyPath bottleneck
- From: Matt Neuburg <email@hidden>
- Date: Tue, 18 Jul 2006 17:44:22 -0700
- Thread-topic: KVO and the observeValueForKeyPath bottleneck
> FROM : George Orthwein
> DATE : Sat Jul 15 07:36:10 2006
>
> For a custom view that responds to a few dozen attributes of the
> controller's current selection....
>
> - (void)observeValueForKeyPath:(NSString *)keyPath
> ofObject:(id)object
> change:(NSDictionary *)change
> context:(void *)context
> {
> NSString *keyPathName;
> if ([keyPath isEqualToString:@"selection.bgImage.color"] == YES){
> // handle special case of this attribute of a relationship
> keyPathName = @"bgImageColor";
> } else {
> // convert "selection.attribute" keypath to appropriate accessor
> name -- by abusing pathExtension method :)
> keyPathName = [keyPath pathExtension];
> }
> [self setValue:[object valueForKeyPath:keyPath] forKey:keyPathName];
> }
>
> So observing "selection.attribute" will call my setAttribute accessor
> with the new value via KVC.
Interestingly, though (or perhaps not, for those who already realized this),
if what you are planning to do when you get notified thru observeValue... is
set a corresponding ivar, it might be much simpler to avoid the entire
problem and use bind:... instead of addObserver:... at the outset.
This goes back to my earlier thread, "two-way bindings and one-way
bindings":
<http://www.cocoabuilder.com/archive/message/cocoa/2006/7/6/166949>
The point there was that if I say bind:..., I get a "one-way" binding, which
in effect means that I start observing the thing I'm bound to. In that
thread I was concentrating on the downside, which is that the thing I'm
bound to does not automatically also start observing me; but now let's talk
about the upside. The upside is that my ivar gets set automatically when the
other object's observed attribute changes - without ever passing through
observeValue...!
So, if what you were going to do was call setValue:forKey: on your own ivar,
you could skip the whole addObserver: thing and just use bind:, because
that's exactly what then *will* happen; setValue:forKey: will be called on
your ivar.
Moreover, if you wanted to do anything else when this happens, you can
implement the accessors to your ivar and do it there.
Moreover, in the case of something like an NSController's "content", this
approach works, when ordinary observing with addObserver: does not. As has
been pointed out several times recently, the change dictionary passed to
observeValue... is empty. But if you start with bind:, it works great; the
new value just gets handed to you directly.
Thus, taking advantage of the aspect of bind:... that you get "for free"
could constitute an economical workaround to the observeValueForKeyPath
bottleneck. Of course this is officially a misuse of bindings, but on the
other hand we've already agreed that the observeValueForKeyPath bottleneck
architecture is wretched, so one may be forgiven for thinking, "any port in
a storm..." m.
--
matt neuburg, phd = email@hidden, <http://www.tidbits.com/matt/>
A fool + a tool + an autorelease pool = cool!
AppleScript: the Definitive Guide - Second Edition!
<http://www.amazon.com/gp/product/0596102119>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden