KVO

作者: 石头89 | 来源:发表于2019-07-28 21:30 被阅读0次

KVO

KVO 的全称是 Key-Value Observing,也叫做 “键值监听”,用于监听对象属性值的变化。

KVO 的使用

// 1.定义监听选项
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | 
                                     NSKeyValueObservingOptionOld;
// 2.添加监听
[obj addObserver:observer forKeyPath:@"keyPath" options:options context:ctx];

// 3.在 observer 类中实现监听方法
// keyPath:被改变的属性的 keyPath
// object:被改变属性的对象
// change:被改变的属性的信息
// context:上下文
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey, id> *)change
                       context:(void *)context {
    // do someting...
    
    // 从 change 中取值用到的 key
    // NSKeyValueChangeNewKey:从 change 中取新值
    // NSKeyValueChangeOldKey:从 change 中取旧值
}

// 4.在不需要监听时要移除监听器
[obj removeObserver:observer forKeyPath:@"keyPath" context: ctx];

KVO 的原理

  1. Runtime 会为被监听属性的类生成一个子类(NSKVONotifying_Xxxx),重写被监听属性的 Setter。
  2. 实例对象的 isa 指向这个子类。
  3. 子类 Setter 的内部调用 Foundation 的 _NSSetXxxValueAndNotify():

_NSSetXxxValueAndNotify() 函数内部工作流程:

  1. [self willChangeValueForKey:@"key"]
  2. [super setXxx:newValue]
  3. [self didChangeValueForKey:@"key"]

在 didChangeValueForKey: 方法内通知监听器:
[observer observeValueForKeyPath:key ofObject:self change:change context:ctx]

KVO 补充

在 Runtime 生成的子类中,除了重写被监听属性的 Setter,还重写了其他几个方法:

  • -(Class)class:这里返回自定义类的 Class 对象,因为子类在应用层是被屏蔽的。
  • -(void)dealloc:释放一些资源。
  • -(Bool)_isKVOA:是否为一个 KVO 机制的类。

通过 class_copyMethodList(Class class, unsigned int *outCount) 函数可以查看一个类中的方法信息。

示例:

unsigned int count;
Class class = object_getClass(obj);
Method *methods = class_copyMethodList(class, &count);

for (int i = 0; i < count; i++) {
    Method method = methods[i];
    SEL selector =  method_getName(method);
    NSString *name = NSStringFromSelector(selector);
    NSLog(@"%@", name);
}

free(methods);

如何手动触发 KVO ?

调用 willChangeValueForKey 和 didChangeValueForKey。

直接修改成员变量的值会触发 KOV 吗?

不会,因为不会调用 Setter。

如果在添加监听器时指定的是 “属性中的属性”,会有什么不同?

示例:[obj addObserver:observer forKeyPath:@"a.b" options:options context:ctx]。

Runtime 会对 obj 和 obj.a 的类生成子类,重写 obj 的 setA: 和 obj.a 的 setB:,当修改 obj.a 或 obj.a.b 时,都会通知监听器,监听器收到的 keyPath 都是 "a.b"。

开发中要避免这种用法,因为监听器不好区分修改的是哪一级的属性值。

相关文章

  • iOS原理篇(一): KVO实现原理

    KVO实现原理 什么是 KVO KVO 基本使用 KVO 的本质 总结 一 、 什么是KVO KVO(Key-Va...

  • 04. KVO使用,原理,本质

    问题 KVO日常使用 KVO原理(KVO本质是什么) 如何手动触发KVO 直接修改成员变量会触发KVO吗 KVO图...

  • 20.iOS底层学习之KVO 原理

    本篇提纲1、KVO简介;2、KVO的使用;3、KVO的一些细节;4、KVO的底层原理; KVO简介 KVO全称Ke...

  • 深入理解KVO

    iOS | KVO | Objective-C KVO的本质是什么,如何手动触发KVO? 1.什么是KVO KVO...

  • OC语法:KVO的底层实现

    一、KVO是什么二、怎么使用KVO三、KVO的底层实现四、KVO常见面试题 一、KVO是什么 KVO全称Key-V...

  • KVO基本使用

    分三部分解释KVO一.KVO基本使用二.KVO原理解析三.自定义实现KVO 一、KVO基本使用 使用KVO,能够非...

  • KVO 解析

    KVO解析(一) —— 基本了解KVO解析(二) —— 一个简单的KVO实现KVO解析(三) —— KVO合规性K...

  • KVO

    目录 1. KVO的使用1.1 KVO基本使用方法1.2 KVO手动触发模式1.3 KVO属性依赖1.4 KVO容...

  • OC语言之KVO与KVC

    KVO 什么是KVO? KVO 是 Key-value observing(键值观察)的缩写。 KVO是Objec...

  • 可能碰到的iOS笔试面试题(7)--KVO-KVC

    KVC-KVO KVC的底层实现? KVO的底层实现? 什么是KVO和KVC? KVO的缺陷? KVO是一个对象能...

网友评论

      本文标题:KVO

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