一丶原理
1.系统会为你监听的XXX类,创建一个NSKVONotifying_XXX子类;
2.为你监听的属性,创建set方法;
3.set方法里,触发observeValueForKeyPath方法;
4.注意的是,XXX的isa指针会指向NSKVONotifying_XXX;
二丶实现
需要关闭objc_msgsend检查;
- (void)ZB_addObserver:(NSObject *_Nullable)observer forKeyPath:(NSString *_Nullable)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context{
//创建子类
NSString *oldClassName = NSStringFromClass([self class]);
NSString *newName = [@"ZB_" stringByAppendingString:oldClassName];
const char *newClassName = [newName UTF8String];
Class myClass = objc_allocateClassPair([self class], newClassName, 0);
//添加方法(俗称重写方法,其实子类本身没有方法);
class_addMethod(myClass, @selector(setName:), (IMP)setName, "v@:@");
objc_registerClassPair(myClass);
//修改isa指针
object_setClass(self, myClass);
objc_setAssociatedObject(self, (__bridge const void *)@"zb", observer, OBJC_ASSOCIATION_RETAIN);
}
void setName(id self,SEL _cmd,NSString *newName){
id class = [self class];
object_setClass(self, class_getSuperclass([self class]));
//修改原来的值
objc_msgSend(self,@selector(setName:),newName);
id observer = objc_getAssociatedObject(self, (__bridge const void *)@"zb");
//通知
objc_msgSend(observer, @selector(observeValueForKeyPath:ofObject:change:context:),self,@"name",@{@"name":newName},nil);
object_setClass(self, class);
}
三丶代码
https://github.com/k373379320/ZBKVO
iOS_技巧(10)KVO手动发送通知
http://www.jianshu.com/p/3f4203868d10
网友评论