• 使用KVO键值监听


    本文章从五个方面介绍KVO(Key-Value-Observer)键值观察者:

    (1)功能介绍

    (2)使用步骤

    (3)应用场景

    (4)原理理解

    (5)相关的面试题

     

    一 功能介绍

    • KVO是OC语言对「观察者设计模式」的一种实现。
    • 只要是NSObject的子类的实例对象,利用KVO机制可以监听该对象的指定属性的值,当属性值发生变化的时候,监听者就能获得通知,就能作出相应的处理。
    • KVO触发机制:一个对象(观察者),监听另一个对象(被观察者)的某属性是否发生变化,若被监听的属性发生了更改,会触发观察者的一个方法(方法名是固定的,类似于代理方法)
    • 使用KVO的好处之一是,不需要给被观察的实例对象添加任何额外的代码,就能对其实施监听。
    • KVO的实现依赖于OC的运行时系统。

     

    二 使用步骤

    1、注册观察者

    [<#要观察的实例对象#> addObserver:<#作为观察者的实例对象#> forKeyPath:<#要观察的实例对象的指定属性名#>
    options:<#选项#> context:<#上下文,可以为KVO的回调方法传值#>];

    关于options参数

    typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {
        //把更改之前的值提供给监听者的回调方法
        NSKeyValueObservingOptionNew ,
        //把更改之后的值提供给监听者的回调方法
        NSKeyValueObservingOptionOld ,
        //把初始化的值提供给监听者的回调方法,一旦注册立马就会调用一次。通常它会带有新值,而不会带有旧值
        NSKeyValueObservingOptionInitial ,
        //分两次调用监听者的回调方法。在值改变之前和值改变之后
        NSKeyValueObservingOptionPrior  
    };

     

    2、在回调方法中处理属性发生的变化

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change
    (NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
        
        if ([keyPath isEqualToString:@"name"]) {
            id oldValue = [change objectForKey:@"old"];
            
            id newValue = [change objectForKey:@"new"];
            
            NSLog(@"%@~%@~%@", change, oldValue, newValue);
        }
    }

     

    3、触发回调方法

    使用setter方法或者KVC更改监听对象的指定属性,才会触发KVO。

     

    4、移除观察者

    注册观察者和移除观察者一定要成对出现。可以在dealloc中移除观察者,也可以在适当的时候提前手动移除观察者。

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

    ps:一般使用KVO崩溃的原因:

    (1)被观察的对象销毁了(比如被观察的对象被一个局部变量持有)

    (2)观察者被释放掉了,但是没有移除监听(比如模态推出,push,pop等)

    (3)注册的监听没有移除掉,又重新注册了一遍监听

     

    三 应用场景

    在MVC设计模式中,负责Model和View之间的同步。

    比如,监听Model层,当Model层的数据发生更改时,同步View中的显示。

     

    四 原理理解

    比如我们要对Person类的实例对象person的name属性利用KVO机制实施监听属性值的变更通知。

    第一步:运行时系统动态创建一个Person的子类:NSKVONotifying_Person

    第二步: 将实例对象person的isa指针由原来的指向Person类,改为指向NSKVONotifying_Person类

    第三步:改写NSKVONotifying_Person类中name属性的setter方法的实现:

    (tips)-willChangevalueForKey:和-didChangeValueForKey:两个方法是KVO机制中向系统发送通知的实现。因此,上面提到的“触发回调方法”中,只说明了通过setter方法和KVC才能触动KVO机制,对属性直接赋值的方法是不能触发的,比如_name = @"XiaoMing";但是在了解KVO的原理之后,只要用上刚刚所知道的那两个方法,就行了。比如:

     

     五 相关的面试题

    (1)KVO与KVC的区别?

    KVC是键值编码,提供了一种使用字符串直接访问和设置对象的属性的方式;

    KVO是键值监听,提供了一种观察实例对象的指定属性的一种机制。

     

    (2)KVO与Notifacation(通知)、delegate(代理)的区别?

    Delegate的特点有:

    1、1对1的传值

    2、支持正向与反向传值(参数、返回值)

    2、可以用require和optional来修饰

    因此在使用delegate时,除了正常的通过参数传值,还可以灵活的运用返回值。

     

    Notification的特点有:

    1、1对多的传值

    2、不关心返回值,单向的传值

    3、NSNotificationCenter单例统一处理发通知

    4、通过不同的唯一通知标识名NotificationName区分不同通知

    5、被观察者主动发出通知

    因此使用Notification一定要谨慎,由于1对多的缘故,避免滥用,不好查问题

    其次就是注意要及时注销掉通知。比如:

     

    KVO的特点有:

    1、1对多

    2、只能监听对象的属性变化,比较局限

    3、只有通过KVC和setter方法才触发KVO

    4、被观察者不用添加任何代码(比如由被观察者发出通知),观察者与被观察者完全解耦

    5、注册观察者时,属性名都是通过字符串来查找,容易出错

    6、KVO的要求是对象必须支持KVC机制(即必须是NSObject的子类)

    7、也是属于单向传值

     

    (3)KVO的优缺点?

    优点:

    1、能够提供一种简单的方法实现两个对象之间的同步,例如model和view之间的同步

    2、能够对非我们创建的对象,即内部对象的状态作出响应,而且不需要改变内部对象的实现

    3、能够提供观察的属性的最新值和先前值

    4、使用的是keyPath来观察属性,因此也可以观察嵌套对象

    5、完成了对观察对象的抽象,因为不需要额外的代码来允许观察值能够被观察

    缺点:

    1、我们观察的属性必须使用string来定义。因此在编译期不会出现警告以及检查

    2、如果我们对属性进行了重构,那么之前KVO的代码需要重写

    3、当释放观察者时需要移除观察者

    4、KVO只能对属性作出反应,而不会对方法作出反应

     

  • 相关阅读:
    博客
    NFS服务配置
    LAMP环境搭建与配置
    Linux系统管理技巧(下)
    Linux系统管理技巧(上)
    LVM
    安装RPM包或源码包
    Linux第四章 文件和目录管理
    MySQL主从配置 : 配置主和从(一) 配置主
    MySQL主从配置:主从介绍
  • 原文地址:https://www.cnblogs.com/cchHers/p/11114907.html
Copyright © 2020-2023  润新知