KVC: Key-Value Coding,即键值编码。通过属性名称字符串间接访问属性的机制。
常用方法
setValue:forKey: 只能访问当前层级属性
ps: [person setValue:@10 forKey:@"age"];
setValue:forKeyPath: 可以访问属性的属性
ps: [person setValue:@10 forKeyPath:@"student.name"];
KVC内部设值原理
![](https://img.haomeiwen.com/i8323741/0348f4c0f6a0eef0.jpg)
person的isa指针先找到person的类对象,在类对象中根据传过来的key值,寻找set[key]:方法,如果set[key]:方法不存在,则接着寻找_set[key]:方法(这两个方法和属性自动生成的set方法无关,即使没有这个属性,只要有对应的方法存在,就会直接调用)。
当这两个方法都不存在时,系统会接着寻找 accessInstanceVariablesDirectly 方法,该方法的意思是是否可以直接访问成员变量,该方法为类方法,返回一个bool值,默认为YES
当该方法返回NO时,则系统认为无法设置value给key,此时会调用 setValue:forUndefinedKey: 方法,抛出异常
当该方法返回YES时,则系统会接着访问成员变量,按照 _key,_isKey,key,isKey的顺序,依次从四种成员变量规则中获取成员变量
当获取到成员变量时,则对该成员变量进行赋值,完成方法调用
当以上四种成员变量都获取不到时,则调用 setValue:forUndefinedKey: 方法,抛出异常
当实例对象不存在 key 名称的属性,只有成员变量时,通过KVC方法赋值,依然可以触发KVO机制,因为在KVC设值方法内部,系统做了KVO相关方法的调用,相当于手动触发了KVO 即 willChangeValueForKey 和 didChangeValueForKey
KVC内部取值原理
![](https://img.haomeiwen.com/i8323741/03838bc455b1e288.jpg)
person的isa指针先找到person的类对象,在类对象中根据传过来的key值,寻找get[key]方法;如果get[key]方法不存在,则接着寻找[key]方法;如果[key]方法不存在,则接着寻找is[key]方法;如果is[Key]方法不存在,则接着寻找_[key]方法。当这四个方法都不存在时,系统会和KVC设值方法的逻辑一样,寻找 accessInstanceVariablesDirectly 方法。
如果该方法返回YES,则系统也和KVC设值方法一样,按照 _key,_isKey,key,isKey的顺序,依次从四种成员变量规则中获取成员变量,返回NO,则抛出异常。
当最终无法获取到成员变量时,系统会调用 valueForUndefinedKey: 方法,抛出异常
通过KVC修改的属性会触发KVO吗?
会触发。无论是否存在setKey方法,都会触发KVO.因为KVC修改对象属性的值过程中会调用对象的willChangeValueForKey:和didChangeValueForKey:方法,所以触发KVO。
网友评论