记得KVO是最早接触的属性与方法相关联的实现方式,也是最简单的方法。
究竟KVO是如何实现的呢?
探究一番:

猜猜会打印出什么?看结果吧:

一个是Person类,另一个是NSKVONotifying_Person类。
其中object_getClassName()方法:
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;

是一个获取对象的真实类型的方法,定义在runtime.h文件中。
前后WQL的类别发生了变化,说明了:
我们在对某个对象完成监听的注册后,编译器会修改监听对象的isa指针,让这个指针指向一个新生成的中间类。
这里要说明的是isa这个指针,isa是一个Class类型的指针,对象的首地址一般是isa变量,同时isa又保存了对象的类对象的首地址。我们通过object_getClass方法来实现就是获取这个对象的元类,即是对象的类对象(Person)的类型。Class方法获得对象的类型。
每一个对象占用的内存中,一部分是父类属性占用的,在父类占用的内存中,又有一部分是父类的父类占用的。isa指针指向的是父类,因此WQL的地址从Person开始,Person的地址从NSObject开始,这三个对象内存的地址都是一样的,通过这个我们能猜到苹果文档中所提到的中间类就是被监听对象的字类,而且为饿了隐藏实现,苹果还重写了这个字类的class方法和description方法来掩人耳目。另外新类相对于父类添加了一个NSKVONotifying_前缀,这个前缀是为了避免多次创建监听字类,节省资源。
大概流程为这样:

加油~
网友评论