Re: an oldie but a goodie: observing properties of collected objects
Re: an oldie but a goodie: observing properties of collected objects
- Subject: Re: an oldie but a goodie: observing properties of collected objects
- From: Ken Thomases <email@hidden>
- Date: Thu, 17 Jun 2010 17:33:46 -0500
On Jun 17, 2010, at 2:21 PM, Matt Neuburg wrote:
> It has been well said by mmalc that "Observing a collection is not the same
> as observing the properties of the objects in a collection." Specifically,
> in that oh-so-common configuration, an NSMutableArray of MSMutableDictionary
> objects, if every dictionary has a key @"name", I might like to get notified
> thru KVO if a @"name" is changed. But there's no simple way to do that. I
> could register as an observe of @"name" for every one of those dictionaries,
> but this is hard to maintain as dictionaries are added to and removed from
> the array (though, as mmalc shows, it can be done).
It's only hard to maintain if you haven't properly implemented the to-many relationship property with mutating accessors. It is trivial if you have.
Proper encapsulation should mean that there is only a tiny number (4 or fewer, I would say) of places in your code which add or remove elements to/from the array.
I'm not sure to which example of mmalc's you're referring, but you should implement the mutating indexed accessors for your to-many relationship properties, and always go through those. So, for example (typed in mail):
-(void)insertObject:(id) object inWidgetsAtIndex:(NSUInteger)index
{
[_widgets insertObject:object atIndex:index];
[object addObserver:self forKeyPath:@"name" options:0 context:myUniqueContext];
}
-(void)insertWidgets:(NSArray *)objects atIndexes:(NSIndexSet *)indexes
{
[_widgets insertObjects:objects atIndexes:indexes];
[_widgets addObserver:self toObjectsAtIndexes:indexes forKeyPath:@"name" options:0 context:myUniqueContext];
}
-(void)removeObjectFromWidgetsAtIndex:(NSUInteger)index
{
[[_widgets objectAtIndex:index] removeObserver:self forKeyPath:@"name"];
[_widgets removeObjectAtIndex:index];
}
-(void)removeWidgetsAtIndexes:(NSIndexSet *)indexes
{
[_widgets removeObserver:self fromObjectsAtIndexes:indexes forKeyPath:@"name"];
[_widgets removeObjectsAtIndexes:indexes];
}
Note that only two of the above methods are necessary, one "insert" and one "remove". Implementing the optional "replace" methods is equally trivial.
If you want to observe multiple properties, just implement a class method which returns the set of keys or key paths that you want to observe on all widgets. Then, loop over that set, repeating the addObserver:... and removeObserver:... calls for each.
Where's the difficulty, again?
Regards,
Ken
_______________________________________________
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