本文转载 李朴之先生博客 http://blog.csdn.net/pucker/article/details/7413280

Objective-C中的KVC与KVO是两种比较重要的技术,这里简要介绍一下这两者的使用方法。

一、KVC

《iOS程序开发方法与实践》中介绍了KVC(Key–Value Coding,键值编码)的基本内容。

简要来说,KVC提供了一种在运行时而非编译时动态访问对象属性与成员变量的方式,也就是说,我们可以用字符串的内容作为属性名称或者成员变量名称进行访问。这种特性有些类似于其他高级编程语言中的反射。

举个例子,例如我们创建了一个类ClassA,其中定义了3个属性p1、p2和p3,以及1个实例方法getValueByPropertyName:,代码如下:

  1. @interface ClassA : NSObject
  2. @property (nonatomic) int p1;
  3. @property (nonatomic) int p2;
  4. @property (nonatomic) int p3;
  5. - (int)getValueByPropertyName:(NSString*)pName;
  6. @end
  7. @implementation ClassA
  8. @synthesize p1 = _p1, p2 = _p2, p3 = _p3;
  9. ...
  10. - (int)getValueByPropertyName:(NSString*)pName
  11. {
  12. if([pName isEqualToString:@"p1"])
  13. {
  14. return self.p1;
  15. }
  16. else if([pName isEqualToString:@"p2"])
  17. {
  18. return self.p2;
  19. }
  20. else if([pName isEqualToString:@"p3"])
  21. {
  22. return self.p3;
  23. }
  24. return 0;
  25. }
  26. @end

方法getValueByPropertyName:用于通过字符串来访问对应的属性值。如果我们想要向ClassA添加几个属性,那么这个方法就还需要添加几个else if语句。而如果使用KVC就会方便许多,代码如下:

  1. - (int)getValueByPropertyName:(NSString*)pName
  2. {
  3. NSNumber* pNumber = [self valueForKey:pName];
  4. return [pNumber intValue];
  5. }

这里有几点需要注意,首先这里的valueForKey:方法用于以字符串调用对象的get属性方法,或者读取成员变量的值;与之相对的是setValue:forKey:,它用于以字符串调用对象的set属性方法,或者修改成员变量的值。第二点需要注意的是,对于基本数据类型,KVC方法会对基本数据类型进行封装(基本数据类型封装为NSNumber,其他结构体类型封装为NSValue)。这里的p1、p2、p3定义为int型,而valueForKey:方法返回的是NSNumber对象,需要再调用intValue取出其中的值。setValue:forKey:方法与之类似,接收NSNumber参数。第三,在使用KVC时,如果找不到字符串对应的属性和成员变量时会怎么样?此时会调用valueForUndefinedKey:或者setValue:forUndefinedKey:这两个方法,默认情况下会抛出异常。第四,默认情况下KVC方法能够直接访问类的私有成员变量,如果我们不想这样,可以重写accessInstanceVariablesDirectly方法,并令其返回NO(默认是返回YES)。KVC方法定义在NSKeyValueCoding类别中,该类别附加于NSObject类上,所以所有对象都具有这些方法。第五,在一些特殊的类的对象上调用KVC方法会有特别的效果。对于数组NSArray、集合NSSet,调用valueForKey:会对每个数组和集合成员调用valueForKey:,并返回新的数组或者集合。

在KVC中还有一种常用技术,称为键值链(Key Path)。键值链是用点将若干键相连的字符串,例如“manufacturer.product.name”。通过在对象上调用valueForKeyPath:或者setValue:forKeyPath:,我们就可以在一条语句中接连调用制定的属性。请看下面的例子:

  1. @interface Product : NSObject
  2. @property NSString* name;
  3. @end
  4. @implementation Product
  5. @synthesize name = _name;
  6. - (void)dealloc
  7. {
  8. self.name = nil;
  9. [super dealloc];
  10. }
  11. @end
  12. @interface Manufacturer : NSObject
  13. @property Product* product;
  14. @end
  15. @implementation Manufacturer
  16. @synthesize product = _product;
  17. -(void)dealloc
  18. {
  19. self.product = nil;
  20. [super dealloc];
  21. }
  22. @end
  23. int main(int argc, const char * argv[])
  24. {
  25. @autoreleasepool
  26. {
  27. Manufacturer* apple = [[[Manufacturer alloc] init] autorelease];
  28. Product* iPhone4S = [[[Product alloc] init] autorelease];
  29. iPhone4S.name = @"iPhone 4S";
  30. apple.product = iPhone4S;
  31. Manufacturer* micro$oft = [[[Manufacturer alloc] init] autorelease];
  32. Product* win8 = [[[Product alloc] init] autorelease];
  33. win8.name = @"Windows 8";
  34. micro$oft.product = win8;
  35. NSArray* manufacturerArray = [NSArray arrayWithObjects:apple, micro$oft, nil];
  36. NSArray* productNameArray = [manufacturerArray valueForKeyPath:@"product.name"];
  37. NSLog(@"productNameArray:\n%@", productNameArray);
  38. }
  39. return 0;
  40. }

首先程序定义了两个类Product与Manufacturer,分别定义商品与制造商。Manufacturer类定义了一个product属性,Product类定义了name属性。在main函数中,我们创建了两个制造商苹果和微软,以及两个商品iPhone4S和Win8,并设置好他们之间的关系。然后程序将两个制造商放入数组中,在数组上调用valueForKeyPath:方法并传入键值链@"product.name"。于是数组首先执行valueForKey:@"product",它会在每个数组成员上调用product属性,获取每个制造商的商品,然后再在每个商品上调用valueForKey:@"name",获取每个制造商的每个商品的名称,并将结果放到另一个数组中。上述程序的输出结果为:

  1. productNameArray:
  2. (
  3. "iPhone 4S",
  4. "Windows 8"
  5. )

使用KVC的好处是非常灵活,但同时也丢失了编译时检查。

Objective-C中的KVC与KVO(上)的更多相关文章

  1. iOS中关于KVC与KVO知识点

    iOS中关于KVC与KVO知识点 iOS中关于KVC与KVO知识点  一.简介 KVC/KVO是观察者模式的一种实现,在Cocoa中是以被万物之源NSObject类实现的NSKeyValueCodin ...

  2. iOS开发中KVC、KVO简介

    在iOS开发中,KVC和KVO是经常被用到的.可以使用KVC对对象的属性赋值和取得对象的属性值,可以使用KVO监听对象属性值的变化.简单介绍一下KVC和KVO. 一:键值编码(KVC) KVC,全称 ...

  3. [转] iOS (OC) 中 KVC 与 KVO 理解

    转自: http://magicalboy.com/kvc_and_kvo/ KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value ...

  4. 【原】iOS中KVC和KVO的区别

    在iOS开发中经常会看到KVC和KVO这两个概念,比较可能混淆,特地区分一下 KVC(Key Value Coding) 1> 概述 KVC:Key Value Coding,键值编码,是一种间 ...

  5. iOS - 详细理解KVC与KVO

    详细理解KVC与KVO 在面试的时候,KVC与KVO有些时候还是会问到的,并且他们都是Objective C的关键概念,在这里我们先做一个简单地介绍: (一)KVC: KVC即指:NSKeyValue ...

  6. KVC 与 KVO 理解

    KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一 ...

  7. KVC 与 KVO 理解-b

    KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一 ...

  8. KVC与KVO的理解

    KVC与KVO是Objective C的关键概念. Key—Value Coding (KVC) 即是指NSKeyValueCoding,一个非正式的Protocol,提供一种机制间接访问对象的属性. ...

  9. KVC与KVO理解

    转载:https://magicalboy.com/kvc_and_kvo/ KVC 与 KVO 理解 KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲 ...

随机推荐

  1. MySQL数据类型和运算符

    mysql支持多种数据类型,主要有下面三种: 数值数据类型 日期/时间类型 字符串类型 整数类型 不同数据类型有不同的取值范围,可存储的值的范围越大,则所需的存储空间也越大. 整数类型主要有: tin ...

  2. CentOS6.5下安装Zabbix

    一.安装环境LAMP 这次安装zabbix全程使用yum进行安装,在于速度快,而且,出错的机会小,如果以后在生产环境上时,也可以先使用可以联网的机器进行安装,安装好以后将机器隔离,这样安装速度更快更方 ...

  3. [转]ListView学习笔记(二)——ViewHolder

    在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自由的定义listview每一列的布局,但当listview有大量的数据需要加载的时候, ...

  4. UML总结---UML中的事物和关系

    UML中的事物 名称 说明 图形 类 相同属性方法的集合 接口 类或组件提供的,可以完成特定功能的一组操作的集合 协作 合作的动作 用例 系统的一个功能 节点 代表可计算的资源 活动类 有多个线程的类 ...

  5. 关于只能上QQ而其他电脑软件(IE/优酷/腾讯视频...)不能联网的解决

    1.应该是Winsock协议配置有问题,所以进行一下重置工作. 开始-cmd-输入netsh winsock reset命令来重置Winsock目录重新初始化网络环境来恢复网络畅通-重启电脑才能生效 ...

  6. BCM_I2C函数更改

    版本:sdk-xgs-robo- 平台:BCM53344 应用:控制POE芯片 描述:POE控制芯片使用PD69200,使用i2c与其通信,每次需要发送15字节数据,并接受15字节的返回数据. 1.更 ...

  7. 【Java面试题】59 Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

    Math类中提供了三个与取整有关的方法:ceil.floor.round,这些方法的作用与它们的英文名称的含义相对应,例如,ceil的英文意义是天花板,该方法就表示向上取整,Math.ceil(11. ...

  8. ImportError: No module named Crypto.Cipher

    from Crypto.Cipher import AES 报错: ImportError: No module named Crypto.Cipher 解决方法: pip install pycry ...

  9. redis windows 版配置使用

    网上下载windows版的redis 在D盘新建redis目录 把下载的redis压缩包解压到redis目录,如图: 打开配置文件 redis.windows.conf 把 SECURITY下的req ...

  10. mongodb php auto increment 自增

    mongodb的自增实现根oracle,postgresql是差不多,都是通过计数器来实现的. oracle自增实现: 实例说明oracle序列用法 postgresql自增实现: postgresq ...