iOS KVO

2020-03-07  本文已影响0人  半路qzg

KVO

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

一、KVO的主要应用场景

应用场景:当数据模型的数据发生改变时,视图组件能动态的更新,及时显示数据模型更新后的数据。

比如:监听scrollView的contentOffset属性,来完成用户滚动时动态改变某些控件的属性实现效果,包括渐变导航栏、下拉刷新控件等效果。

二、KVO实现步骤

1.注册观察者(为被观察这指定观察者以及被观察者属性)

/*

options: 有4个值,分别是:

NSKeyValueObservingOptionOld 把更改之前的值提供给处理方法

NSKeyValueObservingOptionNew 把更改之后的值提供给处理方法

NSKeyValueObservingOptionInitial 把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。

NSKeyValueObservingOptionPrior 分2次调用。在值改变之前和值改变之后。

*///注册一个监听器用于监听指定的key路径

[self.person addObserver:selfforKeyPath:@"name"options:NSKeyValueObservingOptionNew context:nil];

2.实现回调方法

//当key路径对应的属性值发生改变时,监听器就会回调自身的监听方法,如下

-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id>*)change context:(void*)contex{}

3.触发回调方法

3.1>触发kvo可以通过kvc的方法赋值,还可以调用setter方法

3.2>手动触发kvo,willChangeValueForKey:和DidChangeValueForKey:触发

4.移除观察者

//删除指定的key路径监听器

[self.person removeObserver:selfforKeyPath:@"name"];

//删除指定的key路径监听器,只是多了context参数

[self.person removeObserver:selfforKeyPath:@"name"context:nil];


三、KVO的实现原理简要说明

KVO 是基于 runtime 机制实现的 当某个类的属性对象第一次被观察时,系统就会在运行时动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的 setter 方法。派生类在被重写的 setter 方法内实现真正的通知机制。

如果原类为 Person,那么生成的派生类名为 NSKVONotifying_Person 每个类对象中都有一个 isa 指针指向当前类,当一个类对象的第一次被观察,那么 系统会偷偷将 isa 指针指向动态生成的派生类,从而在给被监控属性赋值时执行的是派生类的 setter 方法。

键值观察通知依赖于 NSObject 的两个方法willChangeValueForKey:didChangevlueForKey:;在一个被观察属性发生改变之前, willChangeValueForKey: 一定会被调用,这就 会记录旧的值。而当改变发生后,didChangeValueForKey: 会被调用,继而observeValueForKey:ofObject:change:context: 也会被调用。

补充:KVO 的这套实现机制中苹果还偷偷重写了 class 方法,让我们误认为还是使用的当前类,从而达到隐藏生成的派生类。

上一篇下一篇

猜你喜欢

热点阅读