【问题标题】:What's the difference between Key-Value Coding and NSDictionary?Key-Value Coding 和 NSDictionary 有什么区别?
【发布时间】:2014-08-03 23:39:35
【问题描述】:

Key-Value Coding 和 NSDictionary 有什么区别? KVC 有 addValue:forKey,NSDicationary 有 addObject:forKey,这给我的印象是它们是非常相似的结构。

【问题讨论】:

  • KVC 是一个适用于很多类的概念。 NSDictionary 是一种特定类型的容器。两种完全不同的东西。
  • stackoverflow.com/a/1062573/3055415这个答案的前两段会帮助你理解。

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


【解决方案1】:

What is Key-Value Coding?:

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

NSDictionary Class Reference:

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

所以,

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

Key-Value Coding 通常与 Key-Value Observation 一起使用(见下文),尽管还有其他用途。例如:

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

如果您不确定应该使用什么,我建议您在尝试使用 KVC 之前学习使用 NSDictionary 和基本模型对象。

另请参阅this Stack Overflow answer,其中回顾了一些语法差异。


键值观察

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

这在两个方面变得非常强大:

  1. 您可以使用KVO到observe changes in collection objects
  2. 使用KVO,您可以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;
    }
    

    现在,当lastNamefirstName 发生变化时,任何观察fullName 的人都会收到通知。

【讨论】:

    【解决方案2】:

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

    相比之下,NSDictionary 是一个 Foundation 集合类,代表一个类集群。

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

    【讨论】:

      【解决方案3】:

      我将尝试回答确切的问题。不同之处在于,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,前提是 friendsFriend 对象的集合(例如 NSArray),每个对象都具有名为 firstName 的 KVC 兼容属性。

      但它甚至不止于此——KVC 提供了特殊的键路径元素(如@avg@sumSELF@distinctUnionOfObjects 等),当在键路径中正确使用时,它们可以实现智能评估收集值的累积和汇总,节省大量循环和代码行。它们看起来也很漂亮,而且可读性很强。 例如:[accounts valueForKeyPath:@"transactions.@avg.amount"] 将扫描所有帐户。对于每个帐户,它将再次扫描其transactions,收集他们的amount。然后它将平均一个帐户的所有交易金额,并最终收集并返回一个NSNumbers 的NSArray,其中包含每个帐户的平均金额。这是简洁而强大的编码。

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

      【讨论】:

        猜你喜欢
        • 2012-04-18
        • 2011-05-16
        • 2013-06-24
        • 2013-12-16
        • 2012-01-25
        • 2013-09-22
        • 2020-04-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多