我们知道在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,有兴趣的同学可以去用下。
 
还有一些其他情况,未完待续

最新文章

  1. selenium+python+eclipse开发中遇到的问题
  2. jquery autocomplete实现读取sql数据库自动补全TextBox
  3. Windows系统时间同步出错解决办法
  4. Dapper.NET - ORM(ibatis.Net)
  5. 【nodejs】创建udp套接字的类型参数的含义
  6. Android 静默安装/后台安装
  7. ZOJ 3607贪心算法
  8. 3.1.2 MVC模式和URL访问
  9. thunk技术
  10. 简单分析beyond作曲
  11. nodejs 文件读取一行
  12. 树的三种遍历方式(C语言实现)
  13. 【adb】连接BlueStacks
  14. 用mapreduce 处理气象数据集
  15. python nmap
  16. sklearn—特征工程
  17. HDU 4612 Warm up (边双连通分量+缩点+树的直径)
  18. js数字转换成财务金额
  19. 【TP3.2 + 其他任何PHP框架】编辑、删除、添加数据,返回原分页 (ajax+form两种方式提交均可以)
  20. ubuntu 镜像站部署

热门文章

  1. 图解如何安装MySQL5.0
  2. C#使用Xamarin开发可移植移动应用进阶篇(7.使用布局渲染器,修改默认布局),附源码
  3. View.post() 不靠谱的地方你知道吗?
  4. SourceTree 简单使用 for Mac
  5. python基础教程(五)
  6. [2012-08-21]FreeBSD9.0体验记
  7. carry-检查数据接口返回数据合法性
  8. MySQL视图view/存储过程和函数的使用
  9. Centos 6系统修复grub
  10. 【JavaScript基础系列】决定你的人生能走多远的,是基础。