iOS KVO

作者: 半路qzg | 来源:发表于2020-03-07 16:14 被阅读0次

    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 方法,让我们误认为还是使用的当前类,从而达到隐藏生成的派生类。

    相关文章

      网友评论

          本文标题:iOS KVO

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