我们知道在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. Servlet3.1上传图片示例

    一.前端JSP页面 <%@page pageEncoding="UTF-8"%><!DOCTYPE html><html><head> ...

  2. JavaScript基础-流程控制-if

    流程控制基本概念 默认情况下,程序的运行流程是这样的:运行程序后,系统会按书写从上至下顺序执行程序中的每一行代码,但是这并不能满足我们所有的开发需求 1.png 实际开发中, 我们需要根据不同的条件执 ...

  3. 【渗透课程】第二篇下-HTTP协议的请求与响应深度剖析

    [渗透课程]第二篇下-HTTP协议的请求与响应深度剖析 HTTP1.1目前支持以下7种请求方法: 常见的MIME类型如下: 第一个数字有五种可能的取值: 目录 什么是请求方法?什么是请求头? HTTP ...

  4. 【前端】Github Pages 与域名关联简明教程

    Github Pages 与域名关联简明教程 1. 向你的 Github Pages 仓库添加一个CNAME(一定要*大写*)文件 其中只能包含一个顶级域名,像这样: example.com 如果你是 ...

  5. TCP协议三次握手与四次挥手通俗解析

    TCP/IP协议三次握手与四次握手流程解析 一.TCP报文格式 TCP/IP协议的详细信息参看<TCP/IP协议详解>三卷本.下面是TCP报文格式图: 图1 TCP报文格式 上图中有几个字 ...

  6. jumpserver-0.3.2 堡垒机环境搭建(图文详解)

    下载安装包:https://github.com/jumpserver/jumpserver.git 解压 三.执行快速安装脚本 cd /opt/jumpserver/install pip inst ...

  7. 后端路由项目由 gulp 改为 webpack 的踩坑实录

    前言 公司有个后端路由的项目是用 gulp 作为前端自动化构建工具,最近学习了一下 webpack,深感其强大,一狠心将其改成了 webpack 构建,以下是踩坑实录. gulp 先来说说原来的架构. ...

  8. java枚举类型构造方法为什么是private的

    枚举类型是单例模式的.你需要实例化一次,然后再整个程序之中就可以调用他的方法和成员变量了.枚举类型使用单例模式是因为他的值是固定的,不需要发生改变.更多知识见 http://blog.yemou.ne ...

  9. 团队作业8——Beta 阶段冲刺2rd day

    一.今日站立式会议照片 二.每个人的工作 (1) 昨天已完成的工作: 今天是冲刺阶段的第二天,冲刺第一天我们完成了对于前端界面的改进与完善工作. (2) 今天计划完成的工作: 成员 昨天已完成的工作 ...

  10. 团队作业4——第一次项目冲刺(Alpha版本)5th day

    一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 计时模式已经大致完成了 接下来是记录成绩的部分 四.困难与问题 1.新语言的学习与适应较慢,整体的开发进展达不到预期效果, 2 ...