如何通过RunTime实现KVO?
程序员文章站
2022-04-13 12:56:34
...
首先我们需要思考什么是KVO?
当你观察一个对象时,调用对象的addobserver:forkeypath :options:content时,一个新的NSKVOObservering类会被动态创建。这个类继承自该对象的原本的类,并重写了被观察属性的 setter 方法。重写的 setter 方法会负责在调用原 setter 方法之前willchangevalueforkey和之后didchangevalueforkey,通知所有观察对象:值的更改。最后通过 isa 混写(isa-swizzling)把这个对象的 isa 指针 ( isa 指针告诉 Runtime 系统这个对象的类是什么 ) 指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例。
具体实现:通过runtime实现KVO
/*内部实现
通过runtime动态的创建了person的子类NSKOVNotying_Person,继承person
修改P对象的类型:p对象的isa指针变成了NSKOVNotying_Person
*/
#import "NSObject+WPKVO.h"
#import <objc/message.h>
@implementation NSObject (WPKVO)
//自定义KVO
- (void)WP_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
//self.class是person 主类类型
NSString *oldName = NSStringFromClass(self.class);
NSString *newName = [@"WPKVO" stringByAppendingString:oldName];
//创建一个子类
Class newClass = objc_allocateClassPair(self.class, newName.UTF8String,0);
objc_registerClassPair(newClass);//注册该类
object_setClass(self, newClass);//修改类 把P对象指向新的子类
//子类继承父类,父类有setName方法,子类有吗?
//子类是没有的,但是isa会找父类的方法 动态添加
class_addMethod(newClass, @selector(setName:), (IMP)setName, "aaa@qq.com:@");
}
void setName(id self, SEL _cmd, NSString *name){
NSLog(@"得到======%@",name);
}
上一篇: iOS 底层探索 - 类
下一篇: OC底层探索(十六) KVO底层原理