Difference between objectForKey and valueForKey?
Solution 1:
objectForKey:
is an NSDictionary
method. An NSDictionary
is a collection class similar to an NSArray
, except instead of using indexes, it uses keys to differentiate between items. A key is an arbitrary string you provide. No two objects can have the same key (just as no two objects in an NSArray
can have the same index).
valueForKey:
is a KVC method. It works with ANY class. valueForKey:
allows you to access a property using a string for its name. So for instance, if I have an Account
class with a property accountNumber
, I can do the following:
NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];
[newAccount setAccountNumber:anAccountNUmber];
NSNumber *anotherAccountNumber = [newAccount accountNumber];
Using KVC, I can access the property dynamically:
NSNumber *anAccountNumber = [NSNumber numberWithInt:12345];
Account *newAccount = [[Account alloc] init];
[newAccount setValue:anAccountNumber forKey:@"accountNumber"];
NSNumber *anotherAccountNumber = [newAccount valueForKey:@"accountNumber"];
Those are equivalent sets of statements.
I know you're thinking: wow, but sarcastically. KVC doesn't look all that useful. In fact, it looks "wordy". But when you want to change things at runtime, you can do lots of cool things that are much more difficult in other languages (but this is beyond the scope of your question).
If you want to learn more about KVC, there are many tutorials if you Google especially at Scott Stevenson's blog. You can also check out the NSKeyValueCoding Protocol Reference.
Hope that helps.
Solution 2:
When you do valueForKey:
you need to give it an NSString, whereas objectForKey:
can take any NSObject subclass as a key. This is because for Key-Value Coding, the keys are always strings.
In fact, the documentation states that even when you give valueForKey:
an NSString, it will invoke objectForKey:
anyway unless the string starts with an @
, in which case it invokes [super valueForKey:]
, which may call valueForUndefinedKey:
which may raise an exception.
Solution 3:
Here's a great reason to use objectForKey:
wherever possible instead of valueForKey:
- valueForKey:
with an unknown key will throw NSUnknownKeyException
saying "this class is not key value coding-compliant for the key ".
Solution 4:
As said, the objectForKey:
datatype is :(id)aKey
whereas the valueForKey:
datatype is :(NSString *)key
.
For example:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSArray arrayWithObject:@"123"],[NSNumber numberWithInteger:5], nil];
NSLog(@"objectForKey : --- %@",[dict objectForKey:[NSNumber numberWithInteger:5]]);
//This will work fine and prints ( 123 )
NSLog(@"valueForKey : --- %@",[dict valueForKey:[NSNumber numberWithInteger:5]]);
//it gives warning "Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'" ---- This will crash on runtime.
So, valueForKey:
will take only a string value and is a KVC method, whereas objectForKey:
will take any type of object.
The value in objectForKey
will be accessed by the same kind of object.
Solution 5:
This table represents four differences between objectForKey
and valueForKey
.
// |---------------------|-------------------------|------------------------|
// | | `objectForKey` | `valueForKey` |
// |---------------------|-------------------------|------------------------|
// | Works on ... | NSDictionary | NSDictionary / KVC |
// |---------------------|-------------------------|------------------------|
// | Throws exception | No | Yes (on KVC) |
// |---------------------|-------------------------|------------------------|
// | Feed | NSObject's subclass | NSString |
// |---------------------|-------------------------|------------------------|
// | Usage on KVC | cannot | can |
// |---------------------|-------------------------|------------------------|