kvo

作者: 胡志强 | 来源:发表于2019-09-28 18:17 被阅读0次

简介:KVO全称为Key Value Observing,键值监听机制,由NSKeyValueObserving协议提供支持,NSObject类继承了该协议,所以NSObject的子类都可使用该方法。

应用场景:当数据模型的数据发生改变时,视图组件能动态的更新,及时显示数据模型更新后的数据。
比如:监听scrollView的contentOffset属性,来完成用户滚动时动态改变某些控件的属性实现效果,包括渐变导航栏、下拉刷新控件等效果。

实现原理简要说明:KVO 是基于 runtime 机制实现的 当某个类的属性对象第一次被观察时,系统就会在运行期动态地创建该类的一 个派生类,在这个派生类中重写基类中任何被观察属性的 setter 方法。派生类在 被重写的 setter 方法内实现真正的通知机制。如果原类为 Person,那么生成的派生类名为 NSKVONotifying_Person 每个类对象中都有一个 isa 指针指向当前类,当一个类对象的第一次被观察,那么 系统会偷偷将 isa 指针指向动态生成的派生类,从而在给被监控属性赋值时执行的是派生类的 setter 方法。键值观察通知依赖于 NSObject 的两个方法willChangeValueForKey:didChangevlueForKey:;在一个被观察属性发生改变之前, willChangeValueForKey: 一定会被调用,这就 会记录旧的值。而当改变发生后,didChangeValueForKey: 会被调用,继而observeValueForKey:ofObject:change:context: 也会被调用。
补充:KVO 的这套实现机制中苹果还偷偷重写了 class 方法,让我们误认为还是使用的当前类,从而达到隐藏生成的派生类。

KVO实现步骤

1.注册观察者

/* 
options: 有4个值,分别是:
NSKeyValueObservingOptionOld 把更改之前的值提供给处理方法 
NSKeyValueObservingOptionNew 把更改之后的值提供给处理方法 
NSKeyValueObservingOptionInitial 把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。 
NSKeyValueObservingOptionPrior 分2次调用。在值改变之前和值改变之后。 
 */
//注册一个监听器用于监听指定的key路径
[self.testModel addObserver:self forKeyPath:@"str" options:NSKeyValueObservingOptionNew context:nil];

2.实现回调方法

//当key路径对应的属性值发生改变时,监听器就会回调自身的监听方法,如下
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)contex
    
}

3.移除观察者

//删除指定的key路径监听器
[self.testModel removeObserver:self forKeyPath:@"str"];
//删除指定的key路径监听器,只是多了context参数
[self.testModel removeObserver:self forKeyPath:@"str" context:nil];

KVO原理

1.验证执行对象

在图一种为ZQTextModel创建两个对象 model1和model2,并且坚挺model的str属性,在修改model1和model2的str值时设置断点,在图一中可以看出model1在由于设置了监听,它的isa的指向由ZQTextModel变为了NSKVONotifying_ZQTextModel


图一

2.验证执行方法

在图二中先获取ZQTextModel设置KVO前后「setStr:」的IMP地址然后通过LLDB获取在可执行文件中的具体调用,可以看出在设置KVO后,调用方法变成了_NSSetObjectValueAndNotify


image.png

_NSSetObjectValueAndNotify
_NSSetObjectValueAndNotify 进行断句 _ NS Set Object Value And Notify 其中 “Object”根据属性类型变换

猜测_NSSetObjectValueAndNotify的实现

void _NSSetObjectValueAndNotify(){
    [self willChangValueForKey:@"str"]
    [self setStr:@"str"]
    [self didChangValueForKey:@"str"]
}

验证_NSSetObjectValueAndNotify的实现

在ZQTextModel中重写willChangeValueForKey:didChangeValueForKey:方法

image.png

动态生成子类重写的方法

object_getClass 是获取的isa的指向

- (class)class;
- (void)dealloc;
- (BOOL)isKVOA;

主动出发kvo

直接调用 willChangValueForKey: 和 didChangValueForKey:

相关文章

  • 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/ieoxuctx.html