有人问iOS观察者模式是什么,并介绍一下,然后回答的人张嘴就来NSNotificationCenter怎么使用,然后就GG了,看到这,也没固定思路的我立即去整理了一下。
三问三答。
观察者模式是为了解决什么问题的呢?
观察者模式的定义:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 简而言之,就是A和B,A对B的变化感兴趣,就注册为B的观察者,当B发生变化时通知A,告知B发生了变化。这个也叫做经典观察者模式。
在iOS中通过什么方案来解决的呢?
在iOS中观察者模式的实现有两种方法:Notification、KVO。
当前体系下的具体实现方案呢?
1.Notification
对于感兴趣的A来说,在这里定义通知,也就是注册观察者(A就是观察者,怎么观察的以及观察到了会做些什么)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notice:) name:@"tongzhi" object:nil];
-(void)notice:(id)sender{
NSLog(@"%@",sender);
}
对于变化源B来说,在B这里发出通知
//创建通知对象
NSNotification *notification = [NSNotification notificationWithName:@"tongzhi" object:nil];
//Name是通知的名称 object是通知的发布者(是谁要发布通知,也就是对象) userInfo是一些额外的信息(通知发布者传递给通知接收者的信息内容,字典格式)
// [NSNotification notificationWithName:@"tongzhi" object:nil userInfo:nil];
//发送通知
[[NSNotificationCenter defaultCenter] postNotification:notification];
当然了,还要移除观察者,在dealloc里面
- (void)dealloc {
//删除根据name和对象,如果object对象设置为nil,则删除所有叫name的,否则便删除对应的
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"tongzhi" object:nil];
}
KVO全称叫Key Value Observing,顾名思义就是一种观察者模式用于监听属性的变化,KVO和NSNotification有很多相似的地方,用addObserver:forKeyPath:options:context方法 去观察,用removeObserver:forKeyPath:context去移除观察者,用observeValueForKeyPath:ofObject:change:context:去响应观察者
KVO监听属性的变化非常方便,下面举个例子
//自定义MyTimer类,在.h文件中定义一个属性name
@property (nonatomic, strong) NSString *name;
//自定义ViewController,在controller的.h文件中也定义一个属性myView
@property (nonatomic, strong) UIView *myView;
//在Viewcontroller的.m文件中定义一个button,设置点击事件,在该事件中分别调用上面定义的两个属性
int i = 5;
int sum = 15;
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.frame = CGRectMake(100, 100, 100, 30);
[btn setTitle:@"点击" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(handleTimer:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
_label = [[UILabel alloc ] initWithFrame:CGRectMake(100, 200, 180, 30)];
_label.text = @"当前年龄15岁";
[self.view addSubview:_label];
//创建Mytimer对象
_ourTimer = [[MyTimer alloc ] init];
//观察属性name
[_ourTimer addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew || NSKeyValueChangeOldKey context:nil];
//观察属性myView
[self addObserver:self forKeyPath:@"myView" options:NSKeyValueObservingOptionNew || NSKeyValueChangeOldKey context:nil];
}
//点击事件,分别调用属性
- (void)handleTimer:(UIButton *)btn {
_ourTimer.name = @"小明";
self.myView = nil;
NSLog(@"第一次设置名字");
}
//一旦属性被操作了,这里会自动响应(上面设置观察的属性才会在这响应)
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"name"]) {
NSLog(@"名字发生了改变");
_label.text = [NSString stringWithFormat:@"当前年龄%d岁", i + sum];
sum = i + sum;
} else if ([keyPath isEqualToString:@"myView"]) {
NSLog(@"我的视图");
}
}
//移除
- (void)dealloc {
[_ourTimer removeObserver:self forKeyPath:@"name"];
[self removeObserver:self forKeyPath:@"myView"];
}
如果你喜欢的话,就点个赞吧。
更新:2017-3-30:
KVO是监控自身属性的变化,如uilabel对象的,他监控自身的属性,比如可以有text等
网友评论