I have an NSView
subclass which is bound to the arrangedObjects
of an NSArrayController
. When the array has an item inserted or removed the view is notified. How do I get it to be notified if a model stored in the array has an attribute changed?
Do I need to add my view as an observer to every (relevant) attribute of every item added to the array?
When an item is added to or removed from the array I am notified via observeValueForKeyPath:ofObject:change:context:
in my NSView
subclass. I am not notified of changes to the models stored in the array but I could, every time I am notified of an insertion, add the view as an observer to the new item's attributes. Is this the best way to do this?
I overrode addObserver
for the model class so that I could see what happens and noticed that NSTableView
columns bound to the arrangedObjects
add themselves as observers to the appropriate attributes. Can this be made to happen automagically or do I set up the observations manually?
A big thank you to dreamlax but I think I didn't do a good enough job explaining my problem. My model class was observable and produced the right notifications but I couldn't work out how to observe them without observing every item in the array directly.
I think the documentation for key paths could be improved because I couldn't find anything that explained the very simple change I needed to make. There's some good info the array magic keypaths but no simple "these are the common things" documentation.
Anyway. Previously in my NSView
subclass I had the following:
- (void) bind:(NSString *)binding toObject:(id)observable withKeyPath:(NSString *)keyPath options:(NSDictionary *)options
{
if ([binding isEqualToString:@"observedObjects"]) {
[observable addObserver:self forKeyPath:@"arrangedObjects" options:0 context:nil];
} else {
[super bind:binding toObject:observable withKeyPath:keyPath options:options];
}
}
To get notification of changes to the models within the NSArrayController
's arrangedObjects
all I needed to add was observation of arrangedObjects.name
(for the name
property of my model). So the above code became:
- (void) bind:(NSString *)binding toObject:(id)observable withKeyPath:(NSString *)keyPath options:(NSDictionary *)options
{
if ([binding isEqualToString:@"observedObjects"]) {
[observable addObserver:self forKeyPath:@"arrangedObjects" options:0 context:nil];
[observable addObserver:self forKeyPath:@"arrangedObjects.name" options:0 context:nil];
} else {
[super bind:binding toObject:observable withKeyPath:keyPath options:options];
}
}
That's it! Now if any object in arrangedObjects
gets its name
changed I am notified.