iOS中的观察者模式

作者: 哈哈大p孩 | 来源:发表于2016-06-20 10:35 被阅读6882次

    有人问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等

    相关文章

      网友评论

      • Rooses兵:不错的讲解,把之前不怎么回的看懂了,感谢:grin:
      • 小觉皇free:这不还是在讲NSNotificationCenter怎么使用吗
        Rooses兵:@吉s她Hmm 不不不,一点都不难,真的,你不懂只要去看看原理,然后再照着楼主所写的案例去实验一下,你啥都明白了,我之前还有点迷糊的,现在不迷糊了
        吉s她Hmm:这个观察者模式KVO讲的太难懂了 要不是我会 我直接看不懂你在说些什么!你可以一一对比,去划分他们的不同点,相同点,我感觉这样会更实惠好多人。。。。
        哈哈大p孩:@小觉皇free 观察者模式和NSNotificationCenter是包含关系

      本文标题:iOS中的观察者模式

      本文链接:https://www.haomeiwen.com/subject/zrmmdttx.html