您的位置:首页 > 移动开发 > IOS开发

观察者模式 - 通知/KVO

2015-12-21 22:31 525 查看
观察者模式

观察者模式是一种常用的设计模式,一个对象A想了解另一个对象B的状态是否发生了改变,把A注册成为B的观察者,当B发生改变时,通知A,告知B的变化

观察者模式的实现方式主要有两种:

通知,KVO(KVC/KVO)

【注】比如有一个对象A要发通知,其中有对象B,对象C,对象D来接收通知,需要实现的是,在A中:找到通知中心,创建通知对象,发送通知。

在A,B,C,D中,要找到通知中心,并注册收听的某个频道;当A发消息时候,BCD就会对应的响应相关方法。。。

但是这个过程,你一定要保证“当对象A开始发消息的时候,B,C,D这三个对象已经注册了”

通知和代理的区别:代理是1对1的,通知是多对多的   //比如修改主题等等

通知:

- (IBAction)redBtnClick:(id)sender {
self.view.backgroundColor = [UIColor redColor];
//发送一条广播(命名) 和 发送内容
[[NSNotificationCenter  defaultCenter] postNotificationName:@"changedColor" object:[UIColor redColor]];
}
//注册通知
//在通知中心,注册self为changedColor这条广播的观察者,一旦有任何其他对象,通知通知中心发送changedColor广播,self就能接收到,进而触发后续的nitifacation:方法
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(nitifacation:) name:@"changedColor" object:nil];

-(void)nitifacation:(NSNotification *)no{
//    object 传过来的内容
self.view.backgroundColor = no.object;
}

//重点,通知中心需要手动释放,这也是面试经常问道的问题之一,在arc模式下也需要手动释放的-(void)dealloc
{
//当对象销毁的时候,移除通知中心所注册的通知
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"changedColor" object:nil];
}
KVO

全称(key-value-observer):即观察者模式,对符合KVC键值编码的变量的观察,主要对变量赋值操作的观察

我们假设这样一种情况,有一个数据模型Model,一个字符串string属性,我们希望在ViewController上,用一个UILabel显示这个值,只要

string改变都要对应的修改label 目前可行的办法:1.代理实现  2.通知,但是这样设计,会破坏数据模型的独立性和完整性 这个时候,可以通过设置观察者,在不修改model的前提下,监控model某个属性的改变

例子:有两个界面A和界面B,和一个数据Model,有一个属性name

            界面A有一个UILabel,UILabel显示Model的属性name的值

由界面Apush到界面B,在界面B有一个UITextField,可以修改该model的属性name。

            期望,每次修改后,回到界面A,界面A上label都能对应的更新model的属性name的值

假设VC监听Model的某个属性或者某个成员变量的值是否发生改变之后,对应的更新View

- (void)viewDidLoad {
[super viewDidLoad];
model = [[UserModel alloc] init];
[model setValue:@"校花" forKey:@"name"];
self.myLabel.text = [model valueForKey:@"name"];
//把self注册为model的成员name的观察者
//第一个参数:谁作为观察者
//第二个参数:观察的是那个成员变量
//第三个参数:枚举值,表示观察是新值,旧值
[model addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
}
//那么一旦,该model的成员变量name发生改变,就会自动调用以下方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:@"name"]) {
self.myLabel.text = [change objectForKey:@"new"];
}
}

分享报错:

reason: 'An instance 0x7f82ec5178d0 of class DateModel was deallocated while key value observers were still registered with it
- (void)dealloc
{
[mode removeObserver:self forKeyPath:@"name"];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息