|
In my last blog post on Cocoa programming, I mentioned my new-found love for the NSUndoManager class. While I still love that class, something else interesting happened while working on that sample. A reader who knows far more about Cocoa than I do pointed out that instead of using my fast enumerator:
for (Person *p2 in employees)
{
[self startObservingPerson:p2];
}
I could actually use a different method that will batch-add an observer to an entire array of objects. Then it became a question of dealing with the unwieldy syntax of that method. Basically that method is really flexible and lets me observe subranges within an array - and I only wanted to observe the entire array. This is when the idea was suggested by that very same astute reader that I could create an extension to NSMutableArray that contains a wrapper for this method call. So, here's the extension implementation to NSMutableArray:
@implementation NSMutableArray (ObserverExtension)
- (void)addObserver:(id)observer
toAllObjectsForKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context
{
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:
NSMakeRange(0, [self count])];
[self addObserver:observer
toObjectsAtIndexes:indexes
forKeyPath:keyPath
options:options
context:context];
}
This is ridiculously cool, because now I can invoke this method on an NSMutableArray without ever having subclasses NSMutableArray. The following is my replacement for the fast enumerator I had previously:
[employees addObserver:self
toAllObjectsForKeyPath:@"personName"
options:NSKeyValueObservingOptionOld
context:NULL];
[employees addObserver:self
toAllObjectsForKeyPath:@"expectedRaise"
options:NSKeyValueObservingOptionOld
context:NULL];
Granted, you won't see this in the chapter where you write this code - you only get to invoke this code when you get to Aaron's archiving chapter..but when you do, and you're using the new improved batch-observe stuff here, you'll probably be like me and get a little weepy and emotional at how unbelievably cool this stuff is.
Glad the code was of use to you in the end then Kevin :)
No particular reason. I knew ahead of time that it was an NSMutableArray,
so that's why I made it a category on that. As you said, I could just as
easily have made it an NSArray category and had it apply to a wider range
of arrays.
Be aware though that there is a danger to adding categories to others code
as you don't know if you're overriding some private method or a future
public method. To be safe you could name your new method with a prefix, as
with all global symbols.
Just echoing Martin post about objc categories name clashes... Read bbum
post at
Yes, obviously I could have used prefixes to avoid name clashes.. As it was
just a quick "let's see if this works" sample, I didn't really spend that
much time on prefixing.