What is the difference between objectForKey
and valueForKey
?
I looked both up in the documentation and they seemed the same to me.
I'll try to provide a comprehensive answer here. Much of the points appear in other answers, but I found each answer incomplete, and some incorrect.
First and foremost, objectForKey:
is an NSDictionary
method, while valueForKey:
is a KVC protocol method required of any KVC complaint class - including NSDictionary.
Furthermore, as @dreamlax wrote, documentation hints that NSDictionary
implements its valueForKey:
method USING its objectForKey:
implementation. In other words - [NSDictionary valueForKey:]
calls on [NSDictionary objectForKey:]
.
This implies, that valueForKey:
can never be faster than objectForKey:
(on the same input key) although thorough testing I've done imply about 5% to 15% difference, over billions of random access to a huge NSDictionary. In normal situations - the difference is negligible.
Next: KVC protocol only works with NSString *
keys, hence valueForKey:
will only accept an NSString *
(or subclass) as key, whilst NSDictionary
can work with other kinds of objects as keys - so that the "lower level" objectForKey:
accepts any copy-able (NSCopying protocol compliant) object as key.
Last, NSDictionary's
implementation of valueForKey:
deviates from the standard behavior defined in KVC's documentation, and will NOT emit a NSUnknownKeyException
for a key it can't find - unless this is a "special" key - one that begins with '@' - which usually means an "aggregation" function key (e.g. @"@sum, @"@avg"
). Instead, it will simply return a nil when a key is not found in the NSDictionary - behaving the same as objectForKey:
Following is some test code to demonstrate and prove my notes.
- (void) dictionaryAccess {
NSLog(@"Value for Z:%@", [@{@"X":@(10), @"Y":@(20)} valueForKey:@"Z"]); // prints "Value for Z:(null)"
uint32_t testItemsCount = 1000000;
// create huge dictionary of numbers
NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:testItemsCount];
for (long i=0; i ototal) ? @"valueForKey" : @"objectForKey";
NSString *faster = (vtotal > ototal) ? @"objectForKey" : @"valueForKey";
NSLog (@"%@ takes %3.1f percent longer then %@", slower, 100.0 * ABS(vtotal-ototal) / MAX(ototal,vtotal), faster);
}