Key paths are an insanely helpful concept in objective-c. What are they? Basically they are like key-value coding but nested... plus a touch of magic. With key-value coding you can get at the variables and methods of an object.
NSString *name = @"Corey"; NSLog(@"Output: %@", [name valueForKey:@"length"]); // Output: 5
That example was pretty boring since we can get at the length property in simpler ways, but it's a simple introduction to key-value coding.
What if you have an array of strings and you want to get an array of their lengths (this example is contrived, but just stick with me.) You could loop through the strings and store the lengths in an array or you could use key paths!
NSArray *animals = [NSArray arrayWithObjects:@"pig", @"dog", @"human", @"bear", @"frog", nil]; NSLog(@"Output: %@", [animals valueForKeyPath:@"length"]); // Output: (3, 3, 5, 4, 4)
The same technique applies to dictionaries as well. It's super helpful if you have nested dictionaries. For example assume you have an NSDictionary called animals where the animal name is the key, and the value is an NSDictionary of that animals traits (i.e. legs, teeth, eyes, nipples). Then...
NSLog(@"Legs: %@", [animals valueForKeyPath:@"pig.legs"] // Output: 4
But that's not all! key paths have magic keywords you can throw in like sum, distinctUnionOfObjects and avg.
NSArray *words = [NSArray arrayWithObjects:@"bob", @"dog", @"human", @"bear", @"frog", nil]; NSLog(@"Sum: %@", [words valueForKeyPath:@"@sum.length"]); // Add up all the string lengths NSLog(@"Avg: %@", [words valueForKeyPath:@"@avg.length"]); // Average length of all strings // Sum: 19 // Avg: 3.8
Take a look at the Apple Docs for information about all the operators.
How would you use this in the real world? What if you had a shockingly descriptive object model of your friends, and you wanted to find everyone who had a dad named "Bob". No problem with key paths! Just throw in this NSArray category and you are set!
@implementation NSArray (Find) - (NSArray *)findAllWhereKeyPath:(NSString *)keyPath equals:(id)value { NSMutableArray *matches = [NSMutableArray array]; for (id object in self) { id objectValue = [object valueForKeyPath:keyPath]; if ([objectValue isEqual:value] || objectValue == value) [matches addObject:object]; } return matches; } @end // Implementation example NSArray *friendsWithDadsNamedBob = [friends findAllWhereKeyPath:@"father.name" equals:@"Bob"]
Recent Posts