10.28 KVO原理

来源:互联网 发布:刀哥swift3.0微博源码 编辑:程序博客网 时间:2024/06/11 21:20
研究KVO的时候我们发现系统使用Objective-C 强大的runtime功能实现了这个功能。属性类class中并没有实现KVO通知的相关方案,而是在调用addObserver之后定义属性类的子类subclass,subclass里边实现了属性的setter方法,setter方法中实现发动通知的功能。然后subclass中实现class函数,还让返回属性类的class,再让属性类对象的isa指向subclass,这样就伪装成表面上看还是属性类自己实现的通知功能。通过原理我们可以看出, 必须使用属性方法或者setValue:forKey方法赋值才会发送通知,直接赋值是不会收到通知的。

实际上系统定了一个叫做  NSKVONotifying_ClassTest的子类,子类中实现了

setY: , setX: , class , dealloc , _isKVOA函数,这个 _isKVOA函数应该是个私有函数,用来判断是否kvo框架生成的类, x, y, xy对象的运行时类都指向NSKVONotifying_ClassTest,通过class函数返回的类还是指向ClassTest,但是control对象的不管运行时类还是class函数返回的类都指向 ClassTest。这样就验证了系统是通过定义Classtest类的子类来实现属性方法发送通知的,系统很聪明,子类中并没有实现setZ方法,因为我们并没有对属性z添加观察者。

Objective-C 之 isa

 

每个ObjectiveC对象有个指向其具体类的指针 isa。但Objective-C是一种运行时动态特性很强的语言。换句话说,Objective-C的运行时动态特性决定了某个对象在生命周期内,其所属的类是可能改变的,也就是isa指针有可能改变,Apple把这种技术叫做IsA-swizzling。举个例子,当对某个对象使用了KVO之后,Objective-C实际上是动态的创建了一个该对象所属类的子类,并把该对象的所属类指向这个子类。这时候该对象的isa指针就很不幸的被改变了。实际上,isa指针是Objective-C运行时系统使用到的一个变量,我们在程序中应该尽量不要依赖它。
0 0