美文网首页
KVO底层实现原理

KVO底层实现原理

作者: KeepFighting | 来源:发表于2017-04-22 18:50 被阅读17次

原理:动态生成子类,重写set方法,分发observeValueForKeyPath消息

自定义KVO用到的一些runtime接口

//动态生成一个root类或者某类的派生类
objc_allocateClassPair(Class superclass, const char *name, 
                                         size_t extraBytes) 
//注册类
void objc_registerClassPair(Class cls) 
//给类添加一个方法
BOOL class_addMethod(Class cls, SEL name, IMP imp, 
                                 const char *types) 

//修改对象的指针
Class object_setClass(id obj, Class cls) 

//添加关联属性
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

自定义KVO例子

#import "NSObject+WHJKVO.h"
#import <objc/message.h>


@implementation NSObject (WHJKVO)
- (void)whj_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context {
    // 创建类
    NSString * superClass = NSStringFromClass([self  class]);
    NSString *subClassName = [NSString stringWithFormat:@"whj_%@",superClass];
    const char *name = [subClassName UTF8String];
    Class myClass =  objc_allocateClassPair([self class], name, 0);
    // 注册类
    objc_registerClassPair(myClass);
    // 添加方法
    NSString *methodName = [NSString stringWithFormat:@"set%@:",[keyPath capitalizedString]];
    objc_setAssociatedObject(self, @"methodName", methodName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); //Person 添加关联属性
    class_addMethod(myClass, NSSelectorFromString(methodName), (IMP)myImp, "V@:@");

    //修改指针
    object_setClass(self, myClass);//执行这一行后self,就指向 whj_Person了
    // 添加关联对象,目的保存observer,以备给observer发送消息
    objc_setAssociatedObject(self, @"objc", observer, OBJC_ASSOCIATION_ASSIGN); //whj_Person 添加关联属性

}


void myImp(id self, SEL _cmd,id param) {

    //调用super 的实现
    //先保存子类
    id class = [self class];
    //指针改到父类
    object_setClass(self,class_getSuperclass(class));
    NSString *methodName = objc_getAssociatedObject(self, @"methodName"); // Person 获取关联属性
    //调用父类的方法
    objc_msgSend(self,NSSelectorFromString(methodName),param);

    // 发消息
    id observer =  objc_getAssociatedObject(self, @"objc"); // Person 获取关联属性
    objc_msgSend(observer, @selector(observeValueForKeyPath:ofObject:change:context:),param,self,nil,nil);
    
    //指针改回来 ,这样下次属性变化还回来whj_Person类的myImp方法
    object_setClass(self, class);
    
}


相关文章

  • Today面试

    Runloop 底层原理Kvo 底层原理ARC 底层原理 如何实现GCD 底层原理Block 底层原理Aut...

  • IOS底层(三) KVO底层实现原理

    @[TOC](IOS底层(三) KVO底层实现原理 ) 一,KVO简述 KVO的全称 Key-Value Obse...

  • iOS - KVO

    [toc] 参考 KVO KVC 【 iOS--KVO的实现原理与具体应用 】 【 IOS-详解KVO底层实现 】...

  • KVO的底层实现原理

    KVO的底层实现原理
    KVO的定义(Key-Value Observing) ...

  • iOS - 自定义KVO

    之前我们已经了解过了KVO的底层实现原理,不过呢,在我们开始实现自定义KVO之前再来简单回顾下KVO的实现原理 1...

  • iOS开发面试攻略(KVO、KVC、多线程、锁、runloop、

    KVO & KVC KVO用法和底层原理 使用方法:添加观察者,然后怎样实现监听的代理 KVO底层使用了 isa-...

  • 底层原理

    iOS底层原理总结 - Category的本质 KVO详解及底层实现青少年一定要读的KVO指南 iOS 底层解析w...

  • 2018-02-14

    探究KVO的底层实现原理 addObserver:forKeyPath:options:context:各个参数的...

  • 关于KVO底层Runtime实现的那点事

    有很多公司iOS面试都会被问到KVO底层的实现。网上也有很多篇关于KVO的底层原理,但是都是用willChange...

  • iOS --- KVO

    KVO 的底层实现原理 (1)KVO 是基于 runtime 机制实现的 (2)假如有个对象DoLin(类型为Do...

网友评论

      本文标题:KVO底层实现原理

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