Reputation: 309
What's the difference between Key-Value Coding and NSDictionary? KVC has addValue:forKey and NSDicationary has addObject:forKey, which gives me the impression that they're very similar structures.
Upvotes: 1
Views: 1905
Reputation: 2194
I'll try to answer the exact question. the DIFFERENCE is, an NSDictionary holds arbitrary key-value pairs (e.g. @{ @"Oy":@"Vey", @"name":@"Motti" }
but a normal NSObject
descendant say:
@interface MyClass : NSObject {
NSString *firstName;
NSString *lastName;
}
@end
@implementation
- (id) init {
firstName = "Bobo";
lastName = "Link";
}
@end
MyClass *myObj = [[MyClass alloc] init];
cannot usually be accessed via
[myObj valueForKey:@"firstName"];
It is NOT a collection, and NOT key-value-coding compliant!
Complying with KVC (per specific property) allows you to use an ObjC object AS IF it was an NSDictionary. So if I changed the declaration of the object like thus:
@interface MyClass : NSObject {
NSString *lastName;
}
@property (readwrite, strong, name=firstName) NSString *firstName;
@end
to make it KVC compliant only on firsName
- then calling
[myObj valueForKey:@"firstName"];
would yield the expected value @"Bobo"
.
That's about the difference. However, KVC goes well beyond allowing simple dictionary-like access to objects with key-value semantics.
It introduces the concept of keyPath, where you can "drill" through succession of objects and properties like in [myBankAccount valueForKeyPath:@"addresses.billingAddress.city"]
, or to evaluate and extract collections of values "drilled" at keyPaths (e.g. [personObject valueForKeyPath:@"friends.firstName"]
will collect an NSArray of firstNames of all your friends, provided that friends
is a collection (say NSArray
) of Friend
objects each having a KVC compliant property named firstName
.
But it doesn't stop even there -- KVC provides special key-path elements (like @avg
, @sum
, SELF
, @distinctUnionOfObjects
and others) that when correctly used inside key paths allow for smart evaluation of accumulations and summaries of collected values, saving tons of loops and lines of codes. They also look fancy and are very readable.
For example: [accounts valueForKeyPath:@"[email protected]"]
will scan all the accounts. For each account it will again scan its transactions
, collecting their amount
. It will then average the amounts of all transactions of an account, and will finally collect and return an NSArray
of NSNumber
s, containing average-amounts per account. That's concise and powerful coding.
Other answers already provide lots of good links for documentation.
Upvotes: 0
Reputation: 66302
Key-value coding is a mechanism for accessing an object’s properties indirectly, using strings to identify properties, rather than through invocation of an accessor method or accessing them directly through instance variables. In essence, key-value coding defines the patterns and method signatures that your application’s accessor methods implement.
The
NSDictionary
class declares the programmatic interface to objects that manage immutable associations of keys and values.
So,
NSDictionary
is an object, while key-value coding is a protocolNSDictionary
can store and retrieve objects, while key-value coding must rely on some other form of storageKey-Value Coding is commonly used with Key-Value Observation (see below), although there are other uses. For example:
aaronBrager.apartment.landlord.tenants
).@avg
, @sum
, and @count
.If you're not sure what you should use, I suggest learning to use NSDictionary
and basic model objects before you venture into KVC.
See also this Stack Overflow answer which reviews some of the syntax differences.
Commonly used with Key-Value Coding, Key-Value Observation allows your classes to be notified when the value of a particular key changes. (This is indirectly related to your question.)
There are two areas where this gets really powerful:
With KVO, you can dynamically generate keys based on other keys:
- (NSString *)fullName {
return [NSString stringWithFormat:@"%@ %@",firstName, lastName];
}
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"fullName"]) {
NSArray *affectingKeys = @[@"lastName", @"firstName"];
keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys];
}
return keyPaths;
}
Now anyone observing fullName
will be notified when either lastName
or firstName
changes.
Upvotes: 4
Reputation: 21254
Key Value Coding is a set of conventions for accessing the contents of an object using string identifiers. KVC compliant classes have properties that follow the KVC naming convention. A number of different technologies are layered on top of KVC and depend on it to function. KVC is implemented as an informal protocol on NSObject. KVC can can be used with all descendants of NSObject, as long as the object's properties are compliant with the KVC naming conventions.
NSDictionary, in contrast, is a Foundation collection class representing a class cluster.
KVC is a fundamental concept in Cocoa, the more you know about it the better your applications will be.
Upvotes: 1