iOS--KVC

一直在使用一些方法好比在给模型赋值时使用的setValuesForKeysWithDictionary:jsonObject、改变一些属性时valueForKeyPath等。但面试的时候,面试官一句给我说一个应用场景。我靠,当时我想吃土。结果是固然回答的很差,固然我会使用KVC,我也知道它,但我不能驾驭KVC。前端

有个观点我很认同,咱们作前端的只要会用知道怎么用怎么搭建出界面就行,这样咱们的任务就完成。可是若是知道运行原理,咱们能做出更好的App。就好比组装车的若是知道发动机和刹车运行机制,那么他就能组出性能更棒的车,也能避免好多问题。面试

a、介绍json

咱们能够用KVC直接使用字符串访问成员变量,而不使用setter或者getter方法。缘由是KVC提供了一种在编译时动态访问对象属性和成员变量的方法。它很灵活但同时也失去了在编译期间的检查,若是有错咱们也只能在运行时发现,好比经过使用valueForKeyPath访问一个属性或者其它时,只用当真正运行此处的时候咱们才能发现是否有此属性。api

b、注意点数组

  1. valueForKey:以字符串调用对象的get属性方法,或者读取成员变量的值;setValue:forKey:以字符串调用对象的set属性方法,或者修改为员变量的值。
  2. 对于基本数据类型,KVC方法会对基本数据类型进行封装(基本数据类型封装为NSNumber,其余结构体类型封装为NSValue)。好比int型,valueForKey:方法返回的是NSNumber对象,须要再调用intValue取出其中的值。setValue:forKey:方法与之相似,接收NSNumber参数。
  3. 在使用KVC时,若是找不到字符串对应的属性和成员变量时会怎么样?此时会调用valueForUndefinedKey:或者setValue:forUndefinedKey:这两个方法,默认状况下会抛出异常。通常我本身在模型对象中会重写这两个方法,由于当模型对象中的属性名称和后台返回的json里面某些数据名称不同时,能够很方便的检测出,也能防止崩溃。
  4. 默认状况下KVC方法可以直接访问类的私有成员变量(就上面那个面试,我在苦思冥想以后说KVC能够访问到私有变量,可是面试官一句那要私有干吗。呃  我当时想,完了  无法玩了  彻底不在一个等级上),也能够重写accessInstanceVariablesDirectly方法,并令其返回NO(默认是返回YES)。KVC方法定义在NSKeyValueCoding类别中,该类别附加于NSObject类上,因此全部对象都具备这些方法。在此,反正我不提倡访问私有变量,就如哪位面试官说的。声明私有表明不想被访问到,咱们若是这样干不是逆天而行吗?若是真的在外部使用到此变量,它仍是私有的,大多数状况下只能说明咱们本身的设计有问题,固然也有例外。
  5. 在一些特殊的类的对象上调用KVC方法会有特别的效果。对于数组NSArray、集合NSSet,调用valueForKey:会对每一个数组和集合成员调用valueForKey:,并返回新的数组或者集合。如咱们须要把一个数组里面的字符串取出来将首字母大写,并将新的字符串存到新数组中咱们可使用KVC很方便的达到需求

      [array valueForKeyPath:@“str.capitalizedString”];性能

valueForKeyPath称为键值链(Key Path)。键值链是用点将若干键相连的字符串,经过在对象上调用valueForKeyPath:或者setValue:forKeyPath:。学习

c、干货设计

KVC有些东西常常被忽略掉,可是很使用的小技巧。对象

我对于KVC嵌套知识点学习自一篇简书,感受人家整理的很棒,先感谢人家,在此就厚颜无耻的引用下。字符串

文/水瓶座_iOSer(简书做者)

原文连接:http://www.jianshu.com/p/a6a0abac1c4a

获取数组里的,最大、最小、平均、求和

NSArray *array = @[@"10",@"35",@72,@78,@"1"]; 

NSNumber *sum = [array valueForKeyPath:@"@sum.floatValue"]; 

NSNumber *avg = [array valueForKeyPath:@"@avg.floatValue"]; 

NSNumber *max = [array valueForKeyPath:@"@max.floatValue"]; 

NSNumber *min = [array valueForKeyPath:@"@min.floatValue"];  

删除重复数据

NSArray *array = @[@"name", @"w", @"aa", @"zxp", @"aa"]; //返回的是一个新的数组

 NSArray *newArray = [array valueForKeyPath:@"@distinctUnionOfObjects.self"]; 

NSLog(@"%@", newArray);

一样能够嵌套使用,先剔除name对应值的重复数据再取值

NSArray *array = @[ @{@"title":@"zxp",@"name":@"zhangxiaoping"}, @{@"title":@"zxp2",@"name":@"zhangxiaoping2"}, @{@"title":@"zxp",@"name":@"zhangxiaoping3"}, @{@"title":@"zxp",@"name":@"zhangxiaoping"}];

//根据name字段,来进行重复删除。

NSArray *newArray = [array valueForKeyPath:@"@distinctUnionOfObjects.name"];

//若是要根据title字段来删除重名的写法为`@distinctUnionOfObjects.title` 

NSLog(@"%@", newArray);

/*

print:( zhangxiaoping3, zhangxiaoping2, zhangxiaoping)是一个字符串数组*/

进行实例方法的调用

NSArray *array = @[@"name", @"w", @"aa", @"ZXPing"]; 

NSLog(@"%@", [array valueForKeyPath:@"uppercaseString"]);

至关于数组中的每一个成员执行了uppercaseString方法,而后把返回的对象组成一个新数组返回。既然能够用uppercaseString方法,那么NSString的其余方法也能够,好比[array valueForKeyPath:@“length"]。固然,其余对象的实例方法也能够以此类推来进行调用。

相关文章
相关标签/搜索