观察者模式 - 通知/KVO

察者模式

观察者模式是一种常用的设计模式,一个对象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"];
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值