美文网首页
KVC、KVO的底层原理

KVC、KVO的底层原理

作者: yyggzc521 | 来源:发表于2018-12-09 10:59 被阅读0次

    ------------------KVC---------------------

    KVC是一种通过字符串来访问实例对象属性或变量的机制,使用最多的是用来字典转模型。利用runtime获取对象的所有成员变量, 再根据kvc键值赋值,进行字典转模型
    当给对象发送setValue:forKey 消息时要判断对象是否存在key所对应的属性,如果有,直接赋值;如果没有就调用undefinedKey(默认崩溃,需要重写)

    setValue:forKey的调用顺序
    1. 首先会按照setkey,_setKey顺序找方法
    2. 如果没有那么按 _key, _isKey,key, iskey的顺序搜索成员变量名
    3. 如何还没找到就调用setValue:forUndefinedKey:(默认崩溃,需要重写)
    ValueForKey的调用顺序
    1. 首先会按照getKey, key, isKey,_key顺序找方法
    2. 如果没有那么按 _key, _isKey,key, iskey的顺序搜索成员变量名
    3. 如何还没找到就调用valueForUndefinedKey
    setValueForKey:valueForKey内部查找.png

    ------------------KVO---------------------

    KVO是观察者模式的实现,使用了ISA混写技术
    当被监听对象某个属性发生改变时,监听该属性值变化的对象可以接受到通知,然后通过kvo提供的系统的方法响应一些操作,有利于两个类间的解耦

    原理

    KVO是基于runtime机制实现的,某个对象被观察时,runtime会在运行时动态创建一个新的继承被监听类的子类(NSKVONotifying_ 开头)
    1、然后将被监听类的对象的isa指针指向子类类对象;
    2、并重写子类被观察属性的setter 方法,(这个重写是在运行时而不是编译时实现的,而且是KVO本质);当被监听对象的属性改变时,会触发set方法,但这个方法被重写了,并且在内部调用了didChangeValueForKey方法从而触发通知机制

    KVO机制的特点和触发前提

    • 修改的是属性
    1. 通过setter方法直接修改
    2. 通过 KVC (内部会调用setter方法,从而触发KVO)
    • 修改的是成员变量
      KVC修改成员变量触发KVO.png
    1. KVC修改内部会触发KVO
    2. 手动触发
    KVO图形.png KVO描述.png

    KVO使用步骤

    1. 注册观察者,实施监听
    [self.p1 addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    
    1. 在回调方法中处理属性发生的变化
    // 这个方法时属于 NSObject 类的,任何对象都可以作为观察者
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
        {
            NSLog(@"监听到了%@的%@属性发生了改变", object, keyPath);
            NSLog(@"%@", change);
        }
    
    1. 移除观察者
    [p1 removeObserver:self forKeyPath:@"name"];
    
    • 子类重写被观察属性的setter方法的内部实现
    - (void)setName:(NSString *)name
    {
        
        [self willChangeValueForKey:@"age"];
       [super setName:name];
        [self didChangeValueForKey:@"age"];
    // 这两个方法底层会调用observer的- (void)observeValueForKeyPath: ofObject: change: context:这个方法
    }
    

    拓展

    • KVO和notification(通知)的区别?
    1. 两者都是一对多
    2. notification的优点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,监听范围广
    • KVO与delegate的不同?

    KVO和NSNotification 都是负责发送接收通知,剩下的事情由系统处理,所以不用返回值; delegate 则需要代理联系
    delegate一般是一对一,而这两个可以一对多

    另外需要注意的是,由于KVO这种继承方式的注入是在运行时而不是编译时实现的,如果给定的实例没有观察者,那么KVO不会有任何开销,因为此时根本就没有KVO代码存在。但是即使没有观察者,委托和NSNotification还是得工作,这也是KVO此处零开销观察的优势

    总结

    对比其他的回调方式,KVO机制的运用的实现,更多的由系统支持,相比notification、delegate等更简洁些,并且能够提供观察属性的最新值以及原始值;但是相应的在创建子类、重写方法等等方面的内存消耗是很巨大的

    1、异步:监听通知 主线程:发出通知 接收通知代码在主线程
    2、主线程:监听通知 异步:发出通知 接收通知代码在异步
    总结:接收通知代码 由 发出通知线程决定, KVO也一样

    参考

    相关文章

      网友评论

          本文标题:KVC、KVO的底层原理

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