2013-03-22

Here’s an NSArray Category I’ve used in every single Cocoa project in the last seven years.1 What it does is quite simple, and you can probably guess just by the method names: it lets you filter NSArrays with Key-Value Coding.

@interface NSArray (KeyValueFiltering)
- (id) firstObjectWithValue:(id)value forKeyPath:(NSString*)keypath;
- (NSArray*) filteredArrayWithValue:(id)value forKeyPath:(NSString*)keypath;
@end

It addresse the very, very common task of searching items in list, for example:

Given a list of train trips, show me the ones that start in Paris.

or

In a list of RSS feeds, only display the ones with the label “News”.

Of course, Objective-C developers already have several tools2 for this task:

  • regular loops,
    • C-style (for(int i=0;i<count;i++))
    • or with fast enumeration (for(id obj in array)),
  • NSEnumerators,
  • filtering with NSPredicates, (with -filteredArrayUsingPredicate:)
  • filtering with blocks. (with -enumerateObjectsUsingBlock:)

NSPredicate and block-based filtering are very powerful, but for simple cases, they just make the code hard to read. You may also have noticed that I have a thing for Key-Value Coding.

In a nutshell, filtering NSArrays with Key-Value Coding lets you write this:

NSArray * employees = [...]
Person * ceo = [employees firstObjectWithValue:@"timcook@apple.com" forKeyPath:@"email"];

Of course, you can use keypaths:

Person * steve = [employees firstObjectWithValue:[NSNull null] forKeyPath:@"car.licenseplates"]

(3)

And you can filter with KVC Collection Operators:

NSArray * boxes = [...]
NSArray * emptyBoxes = [boxes filteredArrayWithValue:@0 forKey:@"items.@count"];

That’s it! Easier to read than NSPredicates, shorter than block-based filtering.

You’ll probably have noticed that it only works for simple cases: it can’t execute arbitrary code on the items, and it can only return the objects equal to the passed value. As I said, I use it for the simple cases, which are actually the most common.

That’s if for today! Thanks for reading. You can checkout the code on Github, and criticize it over here on Twitter.

  1. The very first version dates from before ARC, before blocks, before Objective-C 2.0, and before fast enumeration. NSEnumerators FTW! 

  2. Just yesterday, Jim Dalrymple made a great blog post on the Big Nerd Ranch blog about all these options. 

  3. http://osxdaily.com/2010/03/28/steve-jobs-car-has-no-license-plates/