KVO Key- Value- Observing 键-值观察
Cocoa Touch框架为我们提供了一套称为键-值观察的机制, 对象可以通过这套机制得到其他对象特定属性的通知
简单说来, 通知是: 一个中心对象为所有观察者提供变更通知, 主要从广义上关注程序事件
KVO是: 被观察的对象直接向观察者发通知, 绑定于特定对象属性的值
基本的思路图就是这样
三个关键的 API 是这样的
- 添加和移除观察者的方法 (遵循"键-值观察者注册协议:NSKeyValueObserverRegistration")
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context NS_AVAILABLE(10_7, 5_0);
- 被观察者对象的属性发生改变时触发的方法(遵循键-值观察协议: NSKeyValueObserving)
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString*, id> *)change context:(nullable void *)context;
具体使用呢,我举个例子
比如, 现在有一个需求, 当第一个页面上的倒计时到5秒的时候, 控制器自动跳转到第二个控制器. 那么我就需要我的第一个控制器监控倒计时 label 上 text 值的变化,但数字变到5的时候, 自动跳转到第二个控制器, 我知道有很多方法可以实现这个功能, 我现在说一下用 KVO 如何完成这个功能
首先, 第一个控制器的 label 要添加自身控制器为观察者, 观察的 key 值就是, label 的属性 text,
- (void)viewDidLoad {
[super viewDidLoad];
self.timeCountDownLabel.text = @"10";
NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(changeTime) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop]addTimer:timer forMode:NSRunLoopCommonModes];
self.timer = timer;
/* 首先, 第一个控制器的 label 要添加自身控制器为观察者, 观察的 key 值就是, label 的属性 text */
[self.timeCountDownLabel addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)changeTime
{
self.timeCountDownLabel.text = [NSString stringWithFormat:@"%@",@([self.timeCountDownLabel.text intValue] - 1)];
}
然后,但 label 上的 text 的值到5的时候,那么就让控制器自动跳转到第二个控制器
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"text"]) {
if ([change[@"new"] isEqualToString:@"5"]) {
[self performSegueWithIdentifier:@"secondVC" sender:nil];
[self.timer invalidate];
}
}
}
最后, 移除观察者
- (void)dealloc
{
[self.timeCountDownLabel removeObserver:self forKeyPath:@"text"];
}
实现效果是这样的:
以上两篇小文章就蜻蜓点水式地阐述了观察者模式的两种机制, 通知和 KVO,不知大家都懂了没有