-
KVC简介
KVC全称是Key Value Coding,定义在NSKeyValueCoding.h文件中,是一个非正式协议。KVC提供了一种间接访问其属性方法或成员变量的机制,可以通过字符串来访问对应的属性方法或成员变量。 -
KVC常用方法
KVC方法如下图:
-
Getting Values
valueForKey:
返回key对应的属性值 用法[person valueForKey:@"array"]valueForKeyPath:
同样是返回key对应的属性值,但是这里需要传递key的路径valueForKey相当于传入相对路径,valueForKeyPath相当于传入绝对路径。
举例:
想获取student类中的对象的值,[person valueForKeyPath:@"student.subject"]dictionaryWithValuesForKeys:
返回一个字典,其中包含由给定数组中的每个键标识的属性值。valueForUndefinedKey:
当调用valueForKey方法是key在类的属性中没有找到则会调用该方法,可在类中重写该方法,如果没有重写的话则会抛出异常mutableArrayValueForKey:
返回一个可变数组代理,该代理提供对给定键指定的数组(包含不可变数组)的读写访问。 用处在于如果一个NSArray的一个属性如果想修改其中的值可以通过mutableArrayValueForKey返回一个可变数组然后在对数组中的元素进行读写mutableArrayValueForKeyPath:作用同valueForKeyPath同样的传入key值的绝对路径mutableSetValueForKey:(不常用)
返回一个可变集合代理,该代理提供对给定键指定的无序对多关系的读写访问。作用同mutableArrayValueForKeymutableSetValueForKeyPath:(不常用)
作用同valueForKeyPathmutableOrderedSetValueForKey:(不常用)
同mutableArrayValueForKeymutableOrderedSetValueForKeyPath:(不常用)
同mutableArrayValueForKeyPath
-
Setting Values
setValue:forKeyPath:
将由给定键路径标识的属性的值设置为给定值。
[person setValue:@"Swift" forKeyPath:@"student.subject"];setValuesForKeysWithDictionary:
给定一个字典,将字典中的所有key对应的属性value设置成字典中key对应的valuesetNilValueForKey:
如果调用setValue:forKey:方法给标量值(就是简单数据类型如int,float等)赋值的时候value传入nil时调用,如果在子类中重写了该方法会调用子类中的方法,如果没有重写则会抛出异常setValue:forKey:将给定键指定的接收者属性设置为给定值。setValue:forUndefinedKey:
用法原理类似valueForUndefinedKey,传入的key值找不到时调用如果子类重写了该方法则调用子类的方法反之则抛出异常
-
-
KVC实现原理
原理探索冲最基础的setValue:forKey:和valueForKey:入手其他方法都是大同小异,应为KVC的代码是闭源的所以我们只能通过看官方文档猜测苹果的内部实现机制-
取值流程分析
观看官方文档可知分为五个步骤- 先查找
get<key>方法如果没有在查找<key>方法没有再找is<Key>方法_<key>方法如果找到一个则跳转到第三步,否则走第二步(注意如果是NSArray和NSSet下面还应该有两个步骤就是找到是否含有NSArray和NSSet的原始创建方法如果有则创建一个) - 检查类方法
accessInstanceVariablesDirectly是否返回YES,如果返回YES在一次查找实例变量_<key>,_is<Key>,<key>或is<Key>,如果能搜索则直接返回对应值否则跳转到第三步否则跳转到第四步 - 如果检索到的属性值是对象指针,则只需返回结果。
如果该值是NSNumber支持的标量类型,则将其存储在NSNumber实例中,然后将其返回。 如果结果是NSNumber不支持的标量类型,请转换为NSValue对象并返回该对象。 - 执行
valueForUndefinedKey方法,默认会抛出异常 - 流程图如下:
- 先查找
-
设置流程分析
- 查找
set<Key>:或_set<Key>命名的setter,按照这个顺序,如果找到的话,调用这个方法并将值传进去(根据需要进行对象转换)。 - 如果没有发现一个简单的setter,但是
accessInstanceVariablesDirectly类属性返回YES,则查找一个命名规则为_<key>、_is<Key>、<key>、is<Key>的实例变量。根据这个顺序,如果发现则将value赋值给实例变量 - 如果没有发现setter或实例变量,则调用
setValue:forUndefinedKey:方法,并默认提出一个异常,但是一个NSObject的子类可以提出合适的行为。 - 流程图如下
- 查找
-
自定义实现KVC
github地址:github.com/Bore-TuDou/…
-