KVO

作者: 愤怒的八哥 | 来源:发表于2019-02-12 11:17 被阅读16次

    核心原理
    KVO是建立在KVC的基础上。只有在使用KVC准则访问访问器或成员变量的情况下,才可以监视属性的变化。
    NSObject中提供了NSKeyValueObseving类别扩展。
    KVO是通过isa-swizzling技术实现的(这句话是整个KVO实现的重点)。在运行时根据原类创建一个中间类,这个中间类是原类的子类,并动态修改当前对象的isa指向中间类,中间类重写 setter 方法添加了通知代码,并且将class方法重写,返回原类的Class,所以调用object_getClass函数后返回的是其真正的类。所以苹果建议在开发中不应该依赖isa指针,而是通过class实例方法来获取对象类型。
    监听获取

    NSKeyValueObservingOptionNew:change字典包括改变后的值
    NSKeyValueObservingOptionOld:change字典包括改变前的值
    NSKeyValueObservingOptionInitial:注册后立刻触发KVO通知
    NSKeyValueObservingOptionPrior:值改变前是否也要通知(这个key决定了是否在改变前改变后通知两次)
    

    手动触发与禁止

    在setter中调用:
    - (void)willChangeValueForKey:(NSString *)key;
    - (void)didChangeValueForKey:(NSString *)key;
    实现:
    + (BOOL) automaticallyNotifiesObserversForKey:(NSString *)key;
    

    KVO与多线程
    一个需要注意的地方是,KVO 行为是同步的,并且发生与所观察的值发生变化的同样的线程上,没有队列或者 Run-loop 的处理。手动或者自动调用-didChangeValueForKey:会触发 KVO 通知。
    所以,当我们试图从其他线程改变属性值的时候我们应当十分小心,除非能确定所有的观察者都用线程安全的方法处理 KVO 通知。通常来说,我们不推荐把 KVO 和多线程混起来。如果我们要用多个队列和线程,我们不应该在它们互相之间用 KVO。
    KVO 是同步运行的这个特性非常强大,只要我们在单一线程上面运行(比如主队列 main queue),KVO 会保证下列两种情况的发生:
    首先,如果我们调用一个支持 KVO 的 setter 方法,如下所示:

    self.exchangeRate = 2.345;
    

    KVO 能保证所有 exchangeRate 的观察者在 setter 方法返回前被通知到。
    保证移除监听

    removeObserver:forKeyPath:方法将KVO移除
    

    参照
    http://www.cocoachina.com/ios/20180319/22651.html
    https://www.jianshu.com/p/b9f020a8b4c9
    https://github.com/facebook/KVOController

    相关文章

      网友评论

          本文标题:KVO

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