KVC 和 KVO (IOS开发)

    xiaoxiao2022-07-06  201

    KVC(Key-value coding)键值编码

    KVC定义:KVC(Key-value coding)键值编码,就是指iOS的开发中,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。这样就可以在运行时动态地访问和修改对象的属性。

     

    KVC的操作方法由NSKeyValueCoding协议提供,而NSObject就实现了这个协议,也就是说ObjC中几乎所有的对象都支持KVC操作,常用的KVC操作方法如下:

    动态设置: setValue:属性值forKey:属性名(用于简单路径)

                         setValue:属性值forKeyPath:属性路径(用于复合路径,例如Person有一个Account类型的属性,那么person.account就是一个复合属性) 

    动态读取: valueForKey:属性名 

                         valueForKeyPath:属性名(用于复合路径)

     

    KVC使用规则:

    如果是动态设置属性,则优先考虑调用setA方法,如果没有该方法则优先考虑搜索成员变量_a,如果仍然不存在则搜索成员变量a,如果最后仍然没搜索到则会调用这个类的setValue:forUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确设置);

    如果是动态读取属性,则优先考虑调用a方法(属性a的getter方法),如果没有搜索到则会优先搜索成员变量_a,如果仍然不存在则搜索成员变量a,如果最后仍然没搜索到则会调用这个类的valueforUndefinedKey:方法(注意搜索过程中不管这些方法、成员变量是私有的还是公共的都能正确读取);

     

    iOS 开发中KVC的使用场景:

    动态的取值和设值访问和修改私有变量            model和字典的转换修改一些控件的内部属性操作集合高阶消息传递

    (栗子:(UIAlertAction的私有属性_titleTextColor)  [cancelAction setValue:[UIColor yellowColor]  forKey:@"_titleTextColor"];)

     

    键值监听KVO(Key Value Observing)

    KVO定义:KVO即Key-Value Observing,翻译成键值观察。它是一种观察者模式的衍生。其基本思想是,对目标对象的某属性添加观察,当该属性发生变化时,通过触发观察者对象实现的KVO接口方法,来自动的通知观察者。

    KVO其实是一种观察者模式,利用它可以很容易实现视图组件和数据模型的分离,当数据模型的属性值改变之后作为监听器的视图组件就会被激发,激发时就会回调监听器自身。在ObjC中要实现KVO则必须实现NSKeyValueObServing协议,不过NSObject已经实现了该协议,因此几乎所有的ObjC对象都可以使用KVO。

    注意事项:观察者观察的是对象的属性,只遵循KVO变更属性值的方法才会执行KVO的回调方法,如果赋值没有通过setter方法或者KVC,直接修改属性的值,是不会触发KVO机制的,也不会调用回调的方法;

    使用KVO操作常用的方法如下:

    注册指定Key路径的监听器:addObserver: forKeyPath: options:  context:

    删除指定Key路径的监听器:removeObserver: forKeyPath、removeObserver: forKeyPath: context:

    回调监听:observeValueForKeyPath: ofObject: change: context:

    KVO的使用步骤:

    通过addObserver: forKeyPath: options: context:为被监听对象(它通常是数据模型)注册监听器

    重写监听器的observeValueForKeyPath: ofObject: change: context:方法

     

    举个栗子:

    // 添加观察者

    [self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];

    // 监听加载进度

       - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

        if ([keyPath isEqualToString:@"estimatedProgress"]) {

            if (object == self.webView) {

                //在这里进行监听到变化后的操作

            } else {

                [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];

            }

        }

    //移除观察者

      -(void)dealloc {

        if (self.webView) {

            [self.webView removeObserver:self forKeyPath:@"estimatedProgress"];

        }

    }

     

    好文推荐:KVC 详解了解 点击 https://blog.csdn.net/u013983033/article/details/84071483

                       KVO 详解了解 点击 https://blog.csdn.net/u013983033/article/details/83104834

    最新回复(0)