Key-Value Coding与NSDictionary的区别是什么?

时间:2014-08-03 23:39:35

标签: ios objective-c nsdictionary key-value-coding

键值编码和NSDictionary有什么区别? KVC有addValue:forKey和NSDicationary有addObject:forKey,这给我的印象是它们的结构非常相似。

3 个答案:

答案 0 :(得分:3)

What is Key-Value Coding?

  

键值编码是一种间接访问对象属性的机制,使用字符串来标识属性,而不是通过调用访问器方法或直接通过实例变量访问它们。实质上,键值编码定义了应用程序访问器方法实现的模式和方法签名。

NSDictionary Class Reference

  

NSDictionary类声明了对象的编程接口,这些对象管理键和值的不可变关联。

所以,

  • NSDictionary是一个对象,而键值编码是一个协议
  • NSDictionary可以存储和检索对象,而键值编码必须依赖于其他形式的存储

键值编码通常与键值观察(见下文)一起使用,尽管还有其他用途。例如:

  • KVC允许您将字符串中的属性串起来,即使不导入这些类也是如此。 (例如,要查看我的房东的其他租户,您可以检索aaronBrager.apartment.landlord.tenants)。
  • KVC允许使用@avg,例如@sum@countNSDictionary

如果您不确定应该使用什么,我建议您在进入KVC之前学习使用- (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; } 和基本模型对象。

另请参阅collection operators,其中介绍了一些语法差异。


键值观察

键值观察通常与键值编码一起使用,允许在特定键的值发生变化时通知您的类。 (这与你的问题间接相关。)

这有两个领域非常强大:

  1. 您可以将KVO用于this Stack Overflow answer
  2. 使用KVO,您可以observe changes in collection objects

    fullName

    lastNamefirstName发生变化时,任何观察{{1}}的人都会收到通知。

答案 1 :(得分:1)

Key Value Coding是一组使用字符串标识符访问对象内容的约定。符合KVC的类具有遵循KVC命名约定的属性。许多不同的技术都在KVC之上分层,并依赖于它的功能。 KVC在informal protocol上实施为NSObject。只要对象的属性符合KVC命名约定,KVC就可以与NSObject的所有后代一起使用。

相比之下,

NSDictionary是一个代表类集群的Foundation集合类。

KVC是Cocoa中的一个基本概念,你对它的了解越多,你的应用程序就会越好。

答案 2 :(得分:0)

我将尝试回答确切的问题。区别在于,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"];

这不是集合,也不符合键值编码!

如果您是NSDictionary,则遵循KVC(按特定属性)允许您使用ObjC对象作为AS。因此,如果我像这样更改对象的声明:

@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,前提是friendsNSArray对象的集合(例如Friend),每个对象都具有一个与KVC兼容的属性,名为firstName

但是它并没有止步不前-KVC提供了特殊的键路径元素(例如@avg@sumSELF@distinctUnionOfObjects等)在关键路径中正确使用的代码可以对收集值的累加和汇总进行智能评估,从而节省大量的循环和代码行。它们看起来也很漂亮,而且可读性强。 例如:[accounts valueForKeyPath:@"transactions.@avg.amount"]将扫描所有帐户。对于每个帐户,它将再次扫描其transactions,并收集其amount。然后,它将平均一个帐户所有交易的金额,并最终收集并返回NSArrayNSNumber中的JSON.parse(data.allYear).forEach(fiscalYear => { $('#fiscal_year').append('<option>' + fiscalyear + '</option>') }),其中包含每个帐户的平均金额。简洁而强大的编码。

其他答案已经提供了许多很好的文档链接。