1、KVO也就是key-value-observing(键值观察),利用一个key来找到某个属性并监听其值得改变;
1.1、KVO的使用非常简单,调用实例对象的addObserver:forKeyPath:options:context:方法;
1.2、对象在相关属性发生值变化时,会调用观察者的observerValueForKeyPath:ofObject:change:context方法;
2、为什么同一个类创建出来的对象,KVO的对象在修改属性时会多调用一个观察方法?
2.1、从对象本质我们了解到,成员属性或成员方法内存中保存在类对象中,所有实例方法都一样;
2.2、既然同一个类下的实例对象调用同一个方法执行了不同的动作,很有可能这两个实例对象的类对象不一样;
2.3、通过运行时机制中的object_getClass()方法可以验证类对象名为NSKVONotifying_xxxx;
2.4、然而使用实例对象的class方法得到的并不是这个值
3、获取当前类对象的方法实现
3.1、相关代码
1 2 3 4 5 6 7 8 9 10 11 | - (void)methods { unsigned int count; Method *methods = class_copyMethodList(object_getClass(self), &count); NSMutableArray *methodArray = [NSMutableArray array]; for (int i = 0; i < count; i++) { SEL sel = method_getName(methods[i]); [methodArray addObject:NSStringFromSelector(sel)]; } NSLog(@"%@", methodArray); } |
3.2、调用有KVO对象的methods方法可以得到他重写了属性的set方法、class方法、dealloc方法;
3.3、通过superclass可以验证NSKVONotifying_xxxx是原有类对象的子类;
3.4、调用实例对象的methodForSelector:方法可以验证KVO对象set方法的实现为_NSSetFloatValueAndNotify()函数;
3.5、_NSSetFloatValueAndNotify()函数中实现分别调用:
willChangeValueForKey:
set方法
didChangeValueForKey:
其中didChangeValueForKey:方法中调用了监听方法,可重写类中的该三个方法,打印验证;
4、总结:
4.1、参考:Objective-C中对象的分类与本质(isa&superclass)
4.2、KVO的本质是在运行时修改原实例对象的isa指针,使其指向一个新的类对象,该类对象是原类对象的子类;
4.2、类对象中重写了观察属性的set方法、class方法、dealloc方法;
4.3、类对象中set方法的实现实质上为Foundation中的_NSSetFloatValueAndNotify()函数;
4.4、类对象中重写的set方法不仅实现了set方法本身,还调用了观察方法达到监听的目的;
4.5、可通过runtime中的object_getClass()、class_getSuperclass()及isa、superclass属性等验证相关结论;
4.6、还可重写willChangeValueForKey:、didChangeValueForKey:等方法来验证调用顺序;
4.7、可以lldb调试中使用thread backtrack命令查看set方法调用的前后方法验证;