我将尝试回答确切的问题。不同之处在于,NSDictionary 包含任意键值对(例如 @{ @"Oy":@"Vey", @"name":@"Motti" } 但普通的 NSObject 后代说:
@interface MyClass : NSObject {
NSString *firstName;
NSString *lastName;
}
@end
@implementation
- (id) init {
firstName = "Bobo";
lastName = "Link";
}
@end
MyClass *myObj = [[MyClass alloc] init];
通常无法通过以下方式访问
[myObj valueForKey:@"firstName"];
它不是一个集合,也不符合键值编码!
遵守 KVC(每个特定属性)允许您使用 ObjC 对象,因为它是一个 NSDictionary。因此,如果我像这样更改对象的声明:
@interface MyClass : NSObject {
NSString *lastName;
}
@property (readwrite, strong, name=firstName) NSString *firstName;
@end
使其仅在 firsName 上兼容 KVC - 然后调用
[myObj valueForKey:@"firstName"];
将产生预期值@"Bobo"。
这就是区别。然而,KVC 远远超出了允许对具有键值语义的对象进行类似字典的简单访问。
它引入了 keyPath 的概念,您可以在其中“钻取”诸如[myBankAccount valueForKeyPath:@"addresses.billingAddress.city"] 中的一系列对象和属性,或者评估和提取在 keyPaths 处“钻取”的值集合(例如[personObject valueForKeyPath:@"friends.firstName"] 将收集您所有朋友的名字的 NSArray,前提是 friends 是 Friend 对象的集合(例如 NSArray),每个对象都具有名为 firstName 的 KVC 兼容属性。
但它甚至不止于此——KVC 提供了特殊的键路径元素(如@avg、@sum、SELF、@distinctUnionOfObjects 等),当在键路径中正确使用时,它们可以实现智能评估收集值的累积和汇总,节省大量循环和代码行。它们看起来也很漂亮,而且可读性很强。
例如:[accounts valueForKeyPath:@"transactions.@avg.amount"] 将扫描所有帐户。对于每个帐户,它将再次扫描其transactions,收集他们的amount。然后它将平均一个帐户的所有交易金额,并最终收集并返回一个NSNumbers 的NSArray,其中包含每个帐户的平均金额。这是简洁而强大的编码。
其他答案已经提供了很多很好的文档链接。