KVO-理解与简单使用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KVO-理解与简单使用相关的知识,希望对你有一定的参考价值。
KVO
就是key value observing (键值监听 /观察者模式)/是一种回调机制
观察者模式 :
一个目标对象管理所有依赖于他的观察者对象 /并在它自身的状态改变时主动通知观察者对象 /这个制动通知通常是通过调用各观察者对象所提供的接口方法来实现的 /观察者模式比较完美的将目标对象和观察者对象解耦
简单来说 :
在某个对象注册监听者后/在被监听的对象发生改变时/对象会发送一个通知给监听者/以便监听者执行回调
就是每次指定的被观察的对象的属性被修改后 /KVO就会自动通知响应的观察者
KVO和KVC一样都依赖于Runtime的动态及时 /都属于键值编程而且底层实现机制都是isa-swizzling
KVO运用 : 例-监听scrollView的contentOffset属性/来完成用户滚动时动态改变某些控件的属性实现效果(包括渐变导航栏/下拉刷新控件等效果)
KVO使用 : 要求-对象必须能支持KVC机制(NSobject的子类都支持)/(也就是说 赋值通过setter或者KVC)
方法-注册 指定被观察者的属性 /实现回调方法 /移除观察
适用-很适用模型属性被修改后 / 引发 UIView的变化 /当更改属性的值后 /监听对象会立刻得到通知
当需要检测其他类的属性值变化 /但又不想被观察的类知道
有点像FBI监视嫌疑人 /这个时候就可以使用KVO
苹果文档对KVO的实现描述 :
Automatic key-value observing is implemented using a technique called isa-swizzling... When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class ..
也就是说/他使用的技术是ISA调和技术(isa-swizzling) /在我们对某个对象完成监听注册后/编译器会修改所观察到的对象的ISA指针 /可能还会修改了被监听对象的某些属性 /指向一个中间类而不是真正的类 /从某个意义来看 /这是一场骗局
系统实现KVO的步骤:
- 当类A的对象第一次被观察的时候,系统会在运行期动态创建类A的派生类。我们称为B(NSKVONotifying_A)。
- 在派生类B(NSKVONotifying_A)中重写类A的setter方法,B类在被重写的setter方法中实现通知机制。
- 在这个过程中, 被观察对象的isa指针从指向原来A类的, 被KVO机制修改为指向B(NSKVONotifying_A)类, 来实现当前类属性值改变的监听
- 类B(NSKVONotifying_A)重写会 class方法,将自己伪装成类A。类B还会重写dealloc方法释放资源。
- 系统将所有指向类A对象的isa指针指向类B的对象。
KVC同KVO一样 /通过isa-swizzling技术实现 /当观察者被注册为 一个对象的属性 的观察对象 的isa指针被修改(就是当观察者被注册为观察对象 谁的观察对象? 一个对象的属性的观察对象 然后 这个属性的ISA指针被修改) /指向一个中间类 /而不是真是的类 /其结果是 isa指针的值并不一定能反应实例的实际类 /所以不能依靠isa指针来确定对象是否是一个类的成员 /应该使用class方法来确定对象实例的类
ISA指针 :
是一个指向Class类指针 /(专业术语是指向元类pointer to the metaclass 用来指向类的类型) /我们可以通过object_getClass方法来获取这个值 /正常来说 class方法内部的实现就是获取这个ISA指针代表的元类(metaclass) /但是在kvo机制中 /苹果注册监听对象后 通过object_allocateClassPair动态重新创建了一个新类和元类 /此时object_getClass()获取的就不是原来ISA指向的元类 /而是新建的元类
ISA指针的作用 :每个对象都有ISA指针 指向该对象的类 /他告诉Runtime系统这个对象的类是什么 /所以对象注册为观察者时 /isa指针指向新类 /那么这个被观察者的对象就神奇的变成新子类的对象(或实例)了 /因而在该对象上对setting的调用就会调用已重写的setter /从而激活键值通知机制
重写setter方法 :
新类重写了setter方法解析 :KVO的键值观察通知依赖于NSObject的两个方法willChangeValueForKey /didChangeValueForKey
被观察属性发生变化之前 willChangeValueForKey被调用 /通知系统keyPath的属性值即将改变
发生改变后 didChangeValueForKey被调用 /通知系统keyPath的属性值已经改变
之后 - addObserver: forKeyPath: options: context 也会被调用
且重写观察属性的setter方法这种继承方式的注入是在运行时而不是编译时实现的
KVO实现步骤
(options通常传- NSkeyValueObservingOptionNew|NSkeyValueObservingOptonOld)
option是KVO里常见的参数
NSkeyValueObservingOption枚举:
NSkeyValueObservingOptionNew:提供更改前的值
NSkeyValueObservingOptionOld:提供更改后的值
NSkeyValueObservingOptionInitial:观察最初的值(在注册观察服务的时候会调用一次触发方法)
NSkeyValueObservingOptionPrior:分别在值修改前后触发方法(即一次修改两次触发 )
注册
(哪个要注册KVO机制 / 观察的属性值 / 给你观察键值变化的选择 /方便传输你需要的数据 )
- addObserver: forKeyPath: options: context
实现(回调)
(观察的属性值/object??? / 存储了一些变化的数据 比如变化前的数据 变化后的数据 如果注册时context不为空 这里就能收到)
- observeValueForKeyPath: ofObject: change: context:
移除
增加观察与取消观察是成对出现的 所以需要在最后的时候 移除观察者(可以在- dealloc方法了写)
- removeObserver: forKeyPath:
以上是关于KVO-理解与简单使用的主要内容,如果未能解决你的问题,请参考以下文章