iOS KVO基础

在Objc中有一种观察者模式,即是Key Value Observing(KVO)。利用KVO可以很容易实现视图组件和数据模型的分离。当数据模型的值改变时,会马上

在Objc中有一种观察者模式,即是Key Value Observing(KVO)。利用KVO可以很容易实现视图组件和数据模型的分离。当数据模型的值改变时,会马上触发视图组件,更新视图组件。在Objc中要实现KVO,必须实现NSKeyValueObServing协议,所幸的是NSObject已经实现该协议,也就是说,几乎所有的Objc对象都可以使用KVO。

在OC中,KVO的使用步骤一般是:

  • 被监听者通过 addObserver:forKeyPath:options:context: 方法,添加监听
  • 监听者重写 observeValueForKeyPath:ofObject:change:context: 方法,实现监听
  • 被监听者移除监听

简单的实现一下,首先,我需要一个监听对象,所以创建一个Entity

// Entity.h#import <Foundation/Foundation.h>@interface Entity : NSObject@property (nonatomic, copy) NSString *name;/** 因为另外两个属性没有暴露出来 我们只能通过方法来改变 */- (void)changeName1:(NSString *)name1;- (void)changeName2:(NSString *)name2;@end
// Entity.m@interface Entity()@property (nonatomic, copy) NSString *name1;@end@implementation Entity{ @private NSString *_name2;}- (instancetype)init{ self = [super init]; if (self) { _name = @"name"; _name1 = @"name1"; _name2 = @"name2"; } return self;}-(void)changeName1:(NSString *)name1{ _name1 = name1;}-(void)changeName2:(NSString *)name2{ _name2 = name2;}@end

这里 我们建了三个属性,name,name1,name2, 每个name属性都是不一样的定义,这也是我们日常coding中,最常见的三种属性定义方式。

待会我们试着对这三个属性都进行监听,看一下效果如何?

被监听者,已经创建完成了,我们现在需要一个监听者

self.model = [[Entity alloc] init]; UIButton *btn1 = [[UIButton alloc] initWithFrame:CGRectMake(100, 100,200, 30)]; btn1.tag = 100001; [btn1 addTarget:self action:@selector(changeName:) forControlEvents:UIControlEventTouchUpInside]; [btn1 setTitle:@"改变name" forState:UIControlStateNormal]; [self.model addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil]; UIButton *btn2 = [[UIButton alloc] initWithFrame:CGRectMake(100, 200,200, 30)]; btn2.tag = 100002; [btn2 addTarget:self action:@selector(changeName:) forControlEvents:UIControlEventTouchUpInside]; [btn2 setTitle:@"改变值name1" forState:UIControlStateNormal]; [self.model addObserver:self forKeyPath:@"name1" options:NSKeyValueObservingOptionNew context:nil]; UIButton *btn3 = [[UIButton alloc] initWithFrame:CGRectMake(100, 300,200, 30)]; btn3.tag = 100003; [btn3 addTarget:self action:@selector(changeName:) forControlEvents:UIControlEventTouchUpInside]; [btn3 setTitle:@"改变值name2" forState:UIControlStateNormal]; [self.model addObserver:self forKeyPath:@"name2" options:NSKeyValueObservingOptionNew context:nil]; [self.view addSubview:btn1]; [self.view addSubview:btn2]; [self.view addSubview:btn3];

三个按钮分别对应三个属性,点击每个按钮 触发不同的KVO

改变model的属性

- (void)changeName: (UIButton *)btn{ switch (btn.tag) { case 100001: self.model.name = @"change"; break; case 100002: [self.model changeName1:@"change"]; break; case 100003: [self.model changeName2:@"changge"]; break; default: break; }}

当然一定不要忘记了,重写observeValueForKeyPath方法:

//KVO监听回调-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{ NSLog(@"%@", keyPath);}

打印出当前的keypath

一定不要忘记移除监听

-(void)dealloc{ [self.model removeObserver:self forKeyPath:@"name"]; [self.model removeObserver:self forKeyPath:@"name1"]; [self.model removeObserver:self forKeyPath:@"name2"];}

经过试验 我们发现 只有点击第一个按钮,即name属性对应的按钮,才会触发监听。

从这一点,我们可以发现,只有在.h中暴露出来的属性,才能被KVO监听到,.m中的属性,是不能够被监听到。

一个简单的KVO

demo放在:

https://github.com/yangqian111/blog/tree/master/iOS%20KVO初探

未登录用户
全部评论0
到底啦