KVO
key value observing 键值监听。当指定对象的属性被修改后,允许对象接收到通知的机制。
又叫作观察者模式 KVO
先看下面 kvo 代码
1 | // |
看了上面的代码我们再来研究一下什么事KVO
KVO
==键值监听==
当我想知道==一个对象的属性是否发生改变的时候==,做出响应;就需要添加监听。
关键字
keypath
key
的区别。
==keypath
自动寻找子类的属性。==
==key
只会寻找当前类的属性==。
- 添加键值监听
someObject.addObserver: keyPath:
- 键值发生改变
observerValueForKeyPath:
- 移除监听
someObject.removeObserver:ForKey:
OC中使用KVO
OC中KVO调用方式出了上面修饰符其他都一样
1 | - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath |
那什么是KVO?
上面了解了KVO是键值监听。
那么什么是kvo,解决了什么问题呢? 或者是什么场景下需要KVO?KVO的优缺点是什么?
- 解决了什么问题
使得观察者与被观察者完全 ==解藕== 。
- 使用场景
1.使用KVO
实现滑动scrollerView
里对NavigationBar
颜色的渐变;
2.检测进度条
3.上拉加载下拉刷新;
一般KVO的场景是数据,需求时数据变化,比如股票价格的变化。
https://www.jianshu.com/p/8f23536de9d4
KVO的优缺点
- 优点
==能够提供一种简单的方法实现两个对象间的同步==; 例如:model和View之间的同步。
能够对非我们创建的对象,即内部对象的状态改变作出响应, 而且不需要改变内部对象。
能够提供观察的属性的最新值new以及先前值old。
用key Paths来观察属性,因此也可以观察嵌套对象。
完成了对观察对象的抽象,因为不需要额外的代码来允许观察值能够被观察。
- 缺点
- 我们==观察的属性必须使用string来定义==。因此在编译时不会出现警告以及检查;
- 对属性重构将导致我们的观察代码不再可用。
- 复杂的if语句要求对象正在观察多个值,是因为所有的观察代码通过一个方法来指向。
- 释放观察者时不需要移除观察者。
总结
1 | (被观察者testNumb).addObserver(观察者self, forKeyPath: 被观察的属性numb, options: 被观察的选项 new, old, context: 一般写nil) |
被观察者: 需要监听观察的对象,观察内部属性的值变化然后作出响应。观察者: 观察到被观察对象属性变化, 作出响应/反应。
通过上面两句可以看出KVO好处能够将观察者和被观察者完全解藕,运用灵活。但是KVO只能检测类中的属性,并且属性名都是通过String类型来查找,编译器不会不全,容易写错。
KVO和Notification的区别。
相同点
- NSNotification 和KVO都是==类与类之间的通信==。
- 都是负责发出通知,剩下的事情不用管了。
- 两者都可以一对多。
不同点
KVO的使用
- 被观察者addObserver来添加观察者。
- 只要被观察者的keyPath值变化(==只有通过getter和setter方法改变值才会触发KVO==),就会在观察者里面调用方法
ObserveValueForKey Path:ofObject:change:context:
观察者需要实现这个方法来对KVO发出的通知作出响应。 - KVO只能检测类中的属性,并且属性名都是通过String/NSString来查找,编译器不会不全,容易出错。
NSNotification的使用
- 一对多,app中很多控制器都需要知道一个事件,应该用通知。
- 通知不是由被观察者(例如:testNumber)发出的,而是==NSNoticicationCenter(通知中心)统一发出==的,不同通知通过唯一的通知标识名notificationName来区分。
- 需要==被观察者主动发出通知==,然后观察者注册监听后再来进行响应,比KVO多了一个发送通知的步骤,但是优点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,==监听范围广,使用更灵活==。
面试相关问题?
- KVO本质?
- 如何手动触发KVO?
- 直接修改成员变量会触发KVO吗?