iOS之KVO

作者: 请输入账号名 | 来源:发表于2016-07-26 20:20 被阅读98次

    KVO也就是观察者模式(Key Value Observer),KVO可以用于观察对象某个属性的改变,当被观察的属性的值发生变化后会自动的调用对应的方法。例如tableview的位置改变的时候导航栏的透明度的变化情况,亦或者是微博的点赞功能等都可以借鉴KVO。
    使用KVO大体的步骤可分为:注册观察者,重写observeValueForKeyPath:ofObject:change:context:这个方法,然后销毁观察者。这个销毁观察者这一步个人感觉很重要,因为如果不销毁的话,这会造成内存泄漏。下面就用个例子说明下KVO。

    1. 注册成为观察者

    上面已经说到了能观察对象的属性,所以我们先创建一个对象

    // 创建对象
        model = [[WJModel alloc]init];
        model.likes = @10;
        model.love = 20;
    

    这里需要观察的是对象的likeslove值的变化。下面就进行注册观察者:

    [model addObserver:self forKeyPath:@"likes" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    [model addObserver:self forKeyPath:@"love" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    

    注:
    参数1:表示的谁是观察者
    参数2:表明观察属性的路径
    参数3:被观察的值发生变化的时候需要获取的值,这里可以观察到新值和旧值。
    参数4:上下文关系

    2.重写方法

    重写方法的时候可以获取值改变的时刻,以及拿到新值与旧值。而且当被观察的属性发生变化的时候会自动调用这个方法。所以这个方法可能回被调用多次。<其实这也是基于OC的runtime的运行机制的,会在里面的子类里实现setter方法>。

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        NSLog(@"change:%@",change);
        NSLog(@"%@",change[@"new"]);
        // 拿到新值和旧值就可以进行一些操作了。
    }
    

    注:
    参数1 keyPath 被观察的属性的路径
    参数2 object 被观察的对象
    参数3 change 发生改变的值(新值或者旧值)

    由于在其他地方设置了一个点击事件,可以更改属性的值,

    - (IBAction)change:(UIButton *)sender {
        int value = arc4random() % 150;
        self.model.likes = [NSNumber numberWithInt:value];
        self.model.love = value + 78;
    }
    

    控制台的打印提示:
    likes的打印日志:

    // 第一次点击 
    change:{                        
        kind = 1;
        new = 140;
        old = 10;
    }
    
    // 第二次点击
    change:{
        kind = 1;
        new = 13;
        old = 140;
    }
    

    love的点击日志:

    // 第一次点击
    change:{
        kind = 1;
        new = 21;
        old = 20;
    }
    
    // 第二次点击
    change:{
        kind = 1;
        new = 22;
        old = 21;
    }
    

    这两次点击就可以看出可以得知观察属性变化是成功了的,而且这个方法也是调用了多次的。

    3. 销毁观察者

    使用玩了观察着需要把观察者移除,这样可以有效的避免掉内存移除的问题,从而避免了系统的崩溃。
    移除的方法和添加的方法一样,也是需要keyPath的。

    - (void)dealloc {
        [model removeObserver:self forKeyPath:@"likes"];
        [model removeObserver:self forKeyPath:@"love"];
    }
    

    这样使用KVO模式的几个步骤就完成了。

    优点:
    KVO适合任何对象监听另一个对象的改变,这是一个对象与另外一个对象保持同步的一种方法。KVO只能对属性做出反应,不会用来对方法或者动作做出反应。
    1.提供一个简单地方法来实现两个对象的同步。
    2.能对不是我们创建的对象做出反应。
    3.能够提供被观察属性的新值和旧值。
    4.由于用了keypaths 来观察属性,因此也可以观察嵌套对象。

    对比:
    观察属性的改变还有就是可以用到通知中心或者是协议代理。
    1.通知中心NotificationCenter:
    这是一个单例对象,允许当事件发生的时候通知一些对象,满足控制器与一个任意的对象进行通信的目的,这种模式的基本特征就是接收到在该controller中发生某种事件而产生的消息,controller用一个key(通知名称,与keyPath相似),这样对于controller是匿名的,其他的使用同样地key来注册了该通知的对象也能对通知的事件作出反应。
    2.代理
    代理就不多做描述了,都知道怎么用。

    当处理属性层的消息的事件时候,使用KVO,其他的尽量使用代理,除非代码需要处理的东西确实很简单,那么用通知。

    总结:
    1.使用KVO需要注意的是观察的对象属性,一般的基本类型的数据是没有办法进行观察的。
    2.使用观察者的步骤大体来说就是三步:注册观察者及添加需要观察的属性,实现相关的方法,注销观察者对象。
    3.由于keyPath的值是String类型定义的,编译器不会检查也不会出现警告,所以添加和注销的时候keyPath的值须一致,不然添加观察和销毁观察会失败。

    相关文章

      网友评论

          本文标题:iOS之KVO

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