美文网首页IOSiOS Developer
iOS_KVO的原理与实现

iOS_KVO的原理与实现

作者: 丶纳凉 | 来源:发表于2017-05-26 11: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

    相关文章

      网友评论

        本文标题:iOS_KVO的原理与实现

        本文链接:https://www.haomeiwen.com/subject/vcgtfxtx.html