IOSiOS Developer

iOS_KVO的原理与实现

2017-05-26  本文已影响65人  丶纳凉

一丶原理

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

上一篇下一篇

猜你喜欢

热点阅读