欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

如何通过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实现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);
}