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.
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 (
- or with fast enumeration (
for(id obj in array)),
- C-style (
- filtering with NSPredicates, (with
- filtering with blocks. (with
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:@"firstname.lastname@example.org" forKeyPath:@"email"];
Of course, you can use keypaths:
Person * steve = [employees firstObjectWithValue:[NSNull null] forKeyPath:@"car.licenseplates"]
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.
The very first version dates from before ARC, before blocks, before Objective-C 2.0, and before fast enumeration. NSEnumerators FTW! ↩