我们知道在C#中可以通过反射读写一个对象的属性,有时候这种方式特别方便,因为你可以利用字符串的方式去动态控制一个对象。其实由于ObjC的语言特性,你根部不必进行任何操作就可以进行属性的动态读写,这种方式就是Key Value Coding(简称KVC)。

KVC的操作方法由NSKeyValueCoding协议提供,而NSObject就实现了这个协议,也就是说ObjC中几乎所有的对象都支持KVC操作,常用的KVC操作方法如下:

  • 动态设置: setValue:属性值 forKey:属性名(用于简单路径)、setValue:属性值 forKeyPath:属性路径(用于复合路径,例如Person有一个Account类型的属性,那么person.account就是一个复合属性)
  • 动态读取: valueForKey:属性名 valueForKeyPath:属性名(用于复合路径)
 Person *person1=[[Person alloc]init];
//动态设置
[person1 setValue:@"" forKey:@"name"];//简单路径
[person1 setValue:@100000000.0 forKeyPath:@"account.balance"];//复合路径 //动态读取
[person1 valueForKey:@"name" ]//简单路径
[person1 valueForKeyPath:@"account.balance"]//复合路径

注:即便对象属性是非字符串你依然可以使用字符串赋值,KVC就是这么霸气。。

从Dictionary来生成对象

setValuesForKeysWithDictionary, 会为我们把和dictionary的key名字相同的class proerty设置上dict中key对应的value,请注意,你的Dictionary的Key一定一定要和你的类的属性名完全一致。

 -(id) initWithDictionary:(NSMutableDictionary*) jsonObject
{
if((self = [super init]))
{
[self init];
[self setValuesForKeysWithDictionary:jsonObject];
}
return self;
}

如果真的有一些特殊情况使你的Dictionary和你的类的属性肯定有不一样的属性名,那么我们可以重写setValue:(id)value forUndefinedKey:(NSString *)key 方法

 - (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
if([key isEqualToString:@"nameXXX"])
self.name = value;
if([key isEqualToString:@"ageXXX"])
self.age = value;
else
[super setValue:value forKey:key];
}

所以只要重载这个方法,就可以处理了那些无法跟property相匹配的key了,默认的实现是抛出一个NSUndefinedKeyException

如果 这时候server返回的People有了内嵌的json(如Products{product1{count:xx, sumPrice:xx}}, product2{} ….),又该怎么办,能把这个内嵌的json转化成我们的客户端的Product类嘛, 当然可以这时候就需要重载setValue:forKey, 单独处理”Products”这个key, 把它wrapper成我们需要的class

 -(void) setValue:(id)value forKey:(NSString *)key
{
if([key isEqualToString:@"products"])
{
for(NSMutableDictionary *productDict in value)
{
Prodcut *product = [[Product alloc] initWithDictionary:prodcutDict];
[self.products addObject:product];
}
}
}

一些其他的使用场景

例如我们需要把一个数组里的People的名字的首字母大写,并且把新的名字存入新的数组, 这时候通常做法会是遍历整个数组,然后把每个People的name取出来,调用 capitalizedString 然后把新的String加入新的数组中。 有了KVC就有了新做法:
 [array valueForKeyPath:@"name.capitalizedString"] 
我们看到valueForKeyPath, 为什么用valueForKeyPath, 不用valueForKey, 因为valueForKeyPath可以传递关系,例如这里是每个People的name property的String的capitalizedString property, 而valueForKey不能传递这样的关系,所以对于dict里面的dict, 我们也只能用valueForKeyPath。这里我们也看到KVC对于array(set), 做了特殊处理,不是简单操作collection上,而是 针对这些collection里面的元素进行操作,同样KVC也提供更多地操作,例如@sum这些针对collection,有兴趣的同学可以去用下。
 
还有一些其他情况,未完待续

OC——关于KVC的更多相关文章

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

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

  2. OC之KVC,KVO

    KVO简介 在 Cocoa 的模型-视图-控制器 (Model-view-controller)架构里,控制器负责让视图和模型同步.这一共有两步:当 model 对象改变的时候,视图应该随之改变以反映 ...

  3. kvc模式详解

    java利用反射机制访问类的 私有变量.OC的KVC模式也是一样,用来访问私有变量用的. 用字符串去访问对象实例变量的机制. //KVC模式-(void)KVCtest{ [_dm valueForK ...

  4. Object-C目录

    Object学习目录: 1.OC概述 2.OC第一个应用程序 3.OC之类和对象(属性.方法,点语法) 4.OC之类的扩充(self,super关键字.继承.构造函数等)   5.OC之分类Categ ...

  5. OC KVC

    OC KVC KVC 全称 key valued coding 键值编码 在说KVC之前应该简单的了解一下反射机制 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法. 对于任意 ...

  6. OC:属性、点语法、KVC

    //属性的属性 属性定义在一个 .h文件里,在这个.h文件里可以定义实例变量(就是这个类的特征),也可以通过   @protery(属性约束关键字) 属性名字类型 属性名 来定义一些属性,在prope ...

  7. KVC 和 OC字典

    KVC(键值编码)和OC 字典很相似,都是键值存储.但是OC 字典比较灵活,它是一种映射. [dict setObject:<#(id)#> forKey:<#(id<NSCo ...

  8. QF——OC中的KVC,KVO

    KVC: (Key Value Coding) 键值编码 所谓KVC,其实就是不通过set和get方法访问对象属性,而是通过属性名字符串动态的去读取属性.KVC其实也是OC反射机制的一种运用. 之所以 ...

  9. 设计模式之观察者模式(关于OC中的KVO\KVC\NSNotification)

    学习了这么久的设计模式方面的知识,最大的感触就是,设计模式不能脱离语言特性.近段时间所看的两本书籍,<大话设计模式>里面的代码是C#写的,有一些设计模式实现起来也是采用了C#的语言特性(C ...

随机推荐

  1. linux虚拟机ip地址更改

    在虚拟机模式下 进入 cd /etc/sysconfig/network-scripts/ vim ifcfg-eth0 编辑 IPADDR=新的内网ip PREFIX  = 24 (对应255.25 ...

  2. 如何安装Windows 7旗舰版

    如何安装Windows 7旗舰版.. ----------------- Windows 7旗舰版安装的初始画面 ------------------------- 选择好语言后,点击“下一步”按钮, ...

  3. Python3使用Print输出带颜色字体

    Phton3使用print输出带颜色的彩色字体 实现过程:       终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关.       转义序列是以ESC开头,即用\03 ...

  4. Http2改造实践:statusText丢失问题

    背景: 1.项目中的nginx由http1.1改造为http2, 2.代码中采用axios的interceptors做统一返回处理,对于系统逻辑性错误弹窗(例如:表单字段唯一性校验弹窗提示) 现象: ...

  5. WP开发图片保存到独立存储并从独立存储中读取

    需要添加引用命名空间 using System.IO; using System.IO.IsolatedStorage; 1.将图片保存到独立存储空间 using (IsolatedStorageFi ...

  6. 一个小时学会Git

    一.版本控制概要 Git 是一种在全球范围都广受欢迎的版本控制系统.在开发过程中,为了跟踪代码,文档,项目等信息中的变化,版本控制变得前所未有的重要.但跟踪变化远远不能满足现代软件开发行业的协同需求, ...

  7. [ASP.NET MVC]笔记(三) 成员资格、授权和安全性

    阻止CSRF(跨站请求伪造) ASP.NET MVC提供了一个阻止CSRF攻击的好方法 在每个提交的表单中包含 @using (Html.BeginForm("Index", &q ...

  8. MyEclipse使用(一)

    一.配置 window ----> preferences (1)配置 JDK java--->Installed JREs --> Add ---> JRE name --- ...

  9. NHibernate教程(8)--巧用组件

    本节内容 引入 方案1:直接添加 方案2:巧用组件 实例分析 结语 引入 通过前面7篇的学习,有点乏味了~~~这篇来学习一个技巧,大家一起想想如果我要在Customer类中实现一个Fullname属性 ...

  10. SNS团队Beta阶段第五次站立会议(2017.5.26)

    1.立会照片 2.每个人的工作 成员 今天已完成的工作 明天计划完成的工作 罗于婕 生词本功能测试,bug修复 发音图标的改进 龚晓婷 辅助完善历史纪录的功能 对于历史记录功能的测试 林仕庄 继续完善 ...