KVC是Key-value coding 键值编码, KVO是Key-Value Observing 键值观察
这两个一直是面试的时候经常被问到的点
我推荐大家去看小码哥的关于iOS底层原理的腾讯课堂
KVC
KVC的话,概括起来就是两张图:
先说存值的时候setValue:forKey,就会去类的方法列表里面查找,按照setKey:, _setKey:的顺序查找方法,找到了就传递参数,调用方法,找不到的话,就会查看accessInstanceVariaablesDirectly的返回值,默认是YES, 如果是YES的话,就会按照_key,_isKey, key , isKey的顺序查找成员变量,找到了变量就会直接赋值,找不到就调用setValue:forUndefineKey:,并抛出异常NSUnknownKeyException,假如accessInstanceVariaablesDirectly的返回值为NO,那就会直接调用setValue:forUndefineKey:,并抛出异常
取值的时候ValueForKey:,则是按照getKey, key, isKey, _key顺序查找方法,找到了方法就会调用方法,因为取值没有参数,所以也不用传参,假如没有找到方法,就会查看accessInstanceVariaablesDirectly的返回值,如果是YES的话,就会按照_key,_isKey, key , isKey的顺序查找成员变量,找到了变量就会直接取值,找不到就调用value:forUndefineKey:,并抛出异常NSUnknownKeyException,假如accessInstanceVariaablesDirectly的返回值为NO,那就会直接调用value:forUndefineKey:,并抛出异常.
KVO
利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类,当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数,重写父类的set方法,set方法内部依次做如下操作:
调用willChangeValueForKey:
父类原来的setter
调用didChangeValueForKey:
内部会触发监听器(Oberser)的监听方法(observeValueForKeyPath:ofObject:change:context:)