On Jul 7, 2014, at 6:27 PM, Jerry Krinock <[email protected]> wrote:

> On 2014 Jul 07, at 13:42, Luc Van Bogaert <[email protected]> wrote:
> 
>> I'm observing the "selection" property of a NSArrayController object so I 
>> can redraw a custom view whenever the selection of the controllers' objects 
>> changes. This seems to work fine, except that I also receive messages for 
>> the "selection" keypath when sending addObject: or removeObject: to the 
>> controller. 
>> The same happens when observing other keypaths like "selectedObjects" or 
>> "selectedObjects.count".
>> As a result I'm redrawing my custom view time many times when it's not 
>> required. 
>> 
>> Is there a way to avoid this? 
> 
> In this case, I’d wonder if the selection really *is* changing, and in that 
> case you’re getting what you ask for.  Or maybe it’s changing to nil and then 
> changing back to the original selection.  In this case 
> -observeValueForKeyPath:ofObject:change:context: should be invoked twice.

In any case, you're getting what you asked for.  KVO offers no guarantee that 
it will only emit change notifications for "real" changes.  It emits change 
notifications whenever the property was touched in a way that it might have 
changed.  As an observer, it's your responsibility to cope with that.

It will surely generate change notifications for every call of the -willChange… 
/ -didChange… methods.  If it's automatically handling a given key 
(+automaticallyNotifiesObserversForKey: returns YES, which is the default), 
then it will also generate a notification each time the setter for the property 
is called, whether or not the new value is the same as the old value.  If a 
dependent key has been established as per 
+keyPathsForValuesAffectingValueForKey:, then a change in any of the key paths 
will provoke a change notification of the dependent key, whether or not the 
dependent property actually changes its value as a result of the original 
change.

Note that it's not even possible in the general case for KVO to check for a 
real change and avoid emitting the relevant notifications.  An observer can use 
the NSKeyValueObservingOptionPrior option, in which case they get notified 
during the -willChange….  KVO can't even get the new value of the property at 
that point.


> Problems like this can usually be solved by passing 
> NSKeyValuyeObservingOptionNew and/or NSKeyValueObservingOptionOld as options 
> to -addObserver:forKeyPath:options:context:, and processing the information 
> contained in the change dictionaries through a cleverly-crafted filter.

Unfortunately, it's a long-standing problem that NSArrayController does not 
provide the new and old values in the change dictionaries of the notifications 
it emits.  One has to record the last known value of the property named by the 
key path to have the old value and query it for the new value.

Regards,
Ken


_______________________________________________

Cocoa-dev mailing list ([email protected])

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to