美文网首页
关于 KVO 三个问题

关于 KVO 三个问题

作者: 马小峰MXF | 来源:发表于2018-10-23 15:31 被阅读0次

    0、KVO 简介

    KVO(NSKeyValueObserving)为键值观察,是一种非正式协议,它定义了一种机制,允许对象去监听其它对象的某个属性的修改。

    我们可以监听一个对象的属性,包括简单属性,一对一的关系,和一对多的关系(监听一个集合或数组)。一对多关系的监听者会被告知集合变更的类型,以及哪些对象参与了变化。

    1、KVO 和 runtime 有什么联系?

    Objective-C 依托于强大的 runtime 机制来实现 KVO(具体见问题 2).

    2、KVO 的底层实现原理是什么?

    2.0 知识来源

    摘自南峰子技术博客!!!

    http://southpeak.github.io/2015/04/23/cocoa-foundation-nskeyvalueobserving/

    2.1 底层原理

    当我们第一次观察某个对象的属性时,runtime 会创建一个新的继承自这个对象的 class 的subclass。在这个新的 subclass 中,它会重写所有被观察的 key 的 setter,然后将 object 的 isa 指针指向新创建的 class(这个指针告诉 Objective-C 运行时某个 object 到底是什么类型的)。所以 object 神奇地变成了新的子类的实例。

    KVO 底层原理

    2.2 代码示例

    代码示例 测试结果

    从输出中可以看到,bankInstance2 监听 accountBalance 属性后,其实际上所属的类已经不是BankObject 了,而是继承自 BankObject 的 NSKVONotifying_BankObject 类。同时,NSKVONotifying_BankObject 类重写了 setAccountBalance 方法,这个方法将实现如何通知观察者们的操作。当改变 accountBalance 属性时,就会调用被重写的 setAccountBalance 方法,并通过这个方法来发送通知。

    另外我们也可以看到 bankInstance2 对象的打印 [bankInstance2 class] 时,返回的仍然是BankObject。这是苹果故意而为之,他们不希望这个机制暴露在外面。所以除了重写相应的setter,所以动态生成的 NSKVONotifying_BankObject 类还重写了 class 方法,让它返回原先的类。

    3、如何手动实现 KVO?

    3.1 简介

    手动控制通知提供了对 KVO 更精确控制,它可以控制通知如何以及何时被发送给观察者。采用这种方式可以减少不必要的通知,或者可以将多个修改组合到一个修改中。

    实现手动通知的类必须重写 NSObject 中对 automaticallyNotifiesObserversForKey:方法的实现。这个方法是在 NSKeyValueObserving 协议中声明的,其声明如下:

    手动通知需重写该方法

    假如我们希望 Observer 监听 Student 类的 name 属性时实现手动通知,我们需要在修改属性值前调用 willChangeValueForKey:,然后在修改属性值之后调用 didChangeValueForKey:方法。

    3.2 定义一个被观察的对象Student

    Student类有学号、姓名、书籍三个属性 重写 setter 方法,手动调用 willChange 与 didChange

    3.3 定义一个观察者类Observer

    Observer.m 文件需实现 observeValueForKeyPath: ofObject: change: context:方法

    3.4 测试手动通知

    3.4.1 测试代码

    测试代码

    3.4.2 测试结果

    测试结果

    我们可以看到只输出了一次,而不是两次。

    参考文档:

    南峰子技术博客之 KVO

    ObjC 中国 - KVC 和 KVO

    GitHub - leejayID/KVC-KVO: KVC 与 KVO 使用姿势和原理解析

    相关文章

      网友评论

          本文标题:关于 KVO 三个问题

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