Difference between objectForKey and valueForKey?

后端 未结 5 1931
清歌不尽
清歌不尽 2020-11-22 13:25

What is the difference between objectForKey and valueForKey? I looked both up in the documentation and they seemed the same to me.

5条回答
  •  隐瞒了意图╮
    2020-11-22 14:31

    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);
    }
    

提交回复
热议问题