本文源自本人的学习记录整理与理解,其中参考阅读了部分优秀的博客和书籍,尽量以通俗简单的语句转述。引用到的地方如有遗漏或未能一一列举原文出处还望见谅与指出,另文章内容如有不妥之处还望指教,万分感谢。
1. IOS 用什么方式实现对一个对象的KVO ?(KVO的本质是什么?)
利用Runtime API 动态生成一个继承自原有类的子类 NSKVONotifying_XXX, 实现原有类的setter方法 保留成员变量赋值是在原来类中进行,并且让instance对象的isa 指向这个全新的子类;当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数
1> 执行 willChangeValueForKey:
2> 父类原来的setter方法
3> 执行 didChangeValueForKey: ,内部会触发监听器(Observe)的监听方法--> observeValueForKeyPath:ofObject:change:context
2. KVO生成的子类重写哪些方法为什么 ?
setAge: 衍生类重写了属性setter方法,用来赋值;但实际赋值操作仍在原有类中实现
class : 衍生类重写class方法是为了不希望开发者了解到系统API的内部实现。直接返回原有类的类对象
dealloc: 衍生类重写dealloc方法便于管理监听的移除
_isKVOA: 此方法是为了给开发者一个可以判定对象是否添加KVO监听服务
3. 如何手动触发KVO ?
KVO一般来说是自动触发的,当属性值发生改变时就通过监听方法收到消息,那手动触发的场景是不是需要在属性值没有被修改的时候,依然需要收到KVO的监听回调 ,比如轮询查询状态值 ?如果是那就需要通过实例对象调用willChangeValueForKey:和didChangeValueForKey:方法 这样就可以实现了。
疑问 :如果不调用willChangeValueForKey:只调用didChangeValueForKey:可以吗 ?
这是不可以的,因为didChangeValueForKey:内部实现是会检查willChangeValueForKey:方法是否被调用了,如果没有被调用是不会触发监听方法的。
4. 通过KVC修改属性会触发KVO么?直接修改成员变量呢 ?
• 通过KVC修改属性会触发KVO, KVC的全称是Key-Value Coding,俗称“键值编码”,可以通过一个key来访问某个属性,本质上来说KVC内部在修改成员变量的同时是会主动的调用willChangeValueForKey:和didChangeValueForKey:去触发KVO的,所以才会触发。
• 直接修改成员变量不会触发KVO。直接修改成员变量内部并没有做处理只是单纯的赋值,所以不会触发。