Re: Why doesn't -[NSArrayController selection] et al fire keyPathsForValuesAffectingKey?
Re: Why doesn't -[NSArrayController selection] et al fire keyPathsForValuesAffectingKey?
- Subject: Re: Why doesn't -[NSArrayController selection] et al fire keyPathsForValuesAffectingKey?
- From: Jerry Krinock <email@hidden>
- Date: Mon, 5 Apr 2010 03:08:49 -0700
OK, I filed Bug ID# 7827354. (See bottom of this message.) But I don't see the need for MAKVONotificationCenter here...
On 2010 Apr 02, at 22:33, Kyle Sluder wrote:
> I would think that the "right" thing to do would be to subclass NSArrayController and write a
> -canPerformFoo method.
Yes, so I went back and did it the "right" way. To be general, I called it simply -(BOOL)hasSelection
> But you would need to self-observe the selection property,
Indeed, because of the bug in NSArrayController, this doesn't work:
+ (NSSet*)keyPathsForValuesAffectingHasSelection {
return [NSSet setWithObject@"selection"] ;
}
> which is perilous because -removeObserver:forKeyPath: doesn't take a context argument (another
> bug every Cocoa developer should file a duplicate of). So you could use MAKVONotificationCenter (or OFBinding, our analogue) to self-observe.
I already use MAKVONotificationCenter in this project, but I don't see the need for it here. In the array controller's -dealloc,
[self removeObserver:self
forKeyPath:@"selectedObjects"] ;
Why is that perilous? (It seems to work.)
> Perhaps it would be easier to instead put the -canPerformFoo method on your window controller.
I already have my own NSArrayController subclass for other reasons.
**************************************
Apple Bug ID# 7827354
Title: NSArrayController Observeable Methods Don't Do +keyPathsForValuesAffectingKey
Summary: There are four methods which give the selection in some form, and they are all documented to be "observable using key-value observing". However, none of them trigger change notifications when their name is returned in +keyPathsForValuesAffectingKey.
Steps to Reproduce:
1. Require an instance variable which is a function of the current selection in an NSArrayController. Here is a simple example:
// In @interface,
/*!
@brief Returns whether or not any content item in the receiver
is selected.
@details This property should be observeable using KVO.
*/
- (BOOL)hasSelection ;
// In @implementation,
+ (NSSet*)keyPathsForValuesAffectingHasSelection {
return [NSSet setWithObjects:
// Any one of the following should be sufficient.
@"selection",
@"selectedObjects",
@"selectionIndex",
@"selectionIndexes",
nil] ;
}
- (BOOL)hasSelection {
return ([[self selectedObjects] count] > 0) ;
}
2. Bind some binding in a user-interface element, for example the 'enabled' binding of some button which requires a selection in the array controller, to the 'hasSelection' property.
3. Build and run the project.
4. Change the number of items selected in the array controller from 0 to some nonzero number, and vice versa.
Expected Results:
When the number of selected objects changes, the object observing 'hasSelection' should invoke -hasSelection.
Actual Results:
-hasSelection does not get invoked.
Notes:
I am advised by Kyle Sluder that the bug underlying this bug is the bug that +keyPathsForValuesAffectingValueForKey relies on NSKeyValueObservingOptionPrior, and that NSArrayController doesn't support NSKeyValueObservingOptionPrior. See discussion here:
http://lists.apple.com/archives/Cocoa-dev/2010/Apr/msg00088.html
You must read the entire thread because I originally discovered this problem indirectly, and we also hypothesized other causes which turned out to be wrong.
_______________________________________________
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