KVC&KVO

作者: GTMYang | 来源:发表于2018-05-18 14:06 被阅读0次

    KVC

    Key value coding 键值对编程
    OC中KVC相关方法都放在NSKeyValueCoding类别下
    所有继承NSObject的类都能使用KVC的方法

    几个关键方法

     //直接通过Key来取值
    - (nullable id)valueForKey:(NSString *)key;                         
    //通过Key来设值
    - (void)setValue:(nullable id)value forKey:(NSString *)key;          
    //通过KeyPath来取值
    - (nullable id)valueForKeyPath:(NSString *)keyPath;                  
    //通过KeyPath来设值
    - (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;  
    
    //默认返回YES,表示如果没有找到Set<Key>方法的话,会按照_key,_iskey,key,iskey的顺序搜索成员,设置成NO就不这样搜索
    + (BOOL)accessInstanceVariablesDirectly;
    // 如果Key不存在,且没有KVC无法搜索到任何和Key有关的字段或者属性,则会调用这个方法,默认是抛出异常。
    - (nullable id)valueForUndefinedKey:(NSString *)key;
    // 
    - (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
    // 如果你在SetValue方法时面给Value传nil,则会调用这个方法
    - (void)setNilValueForKey:(NSString *)key;
    

    集合运算符

    @avg, @count , @max , @min ,@sum

    集合对象运算符

    @distinctUnionOfObjects // 返回数组(去掉重复)
    @unionOfObjects // 返回数组

    使用场景

    动态地取值和设值
    用KVC来访问和修改私有变量
    Model和字典转换
    修改一些控件的内部属性
    操作集合
    用KVC实现高阶消息传递(当对容器类使用KVC时,valueForKey:将会被传递给容器中的每一个对象)

    KVO

    KVO 即 Key-Value Observing,是一种观察者模式的衍生。
    KVO相关方法定义在NSKeyValueObserving类别下
    所有继承了NSObject的类型,都能使用KVO

    注册与解除注册

    - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
    
    /*
    options
    NSKeyValueObservingOptionNew:change字典包括改变后的值
    NSKeyValueObservingOptionOld:  change字典包括改变前的值
    NSKeyValueObservingOptionInitial:  注册后立即触发一次KVO通知
    NSKeyValueObservingOptionPrior:  值改变前是否也要通知(这个key决定了是否在改变前改变后都通知
    */
    

    处理变更通知

    // 重写Observer对象的该方法
    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(id)object
                            change:(NSDictionary *)change
                           context:(void *)context
    

    手动KVO(禁用KVO)

    // 该方法返回NO就禁用
    + (BOOL) automaticallyNotifiesObserversForKey:(NSString *)key
    

    键值观察依赖键

    // 重写
    + (NSSet<NSString *> *)keyPathsForValuesAffecting<#DependentKey#>
    // 或者重写
    + (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key
    

    KVO底层实现

    1. 编译器创建被观察对象的类的子类NSKVONotifying_<OBJNmae>
    2. 子类中重写被观察属性的setter方法,增加调用触发处理代码的方法
    - (void)willChangeValueForKey:(NSString *)key;
    - (void)didChangeValueForKey:(NSString *)key;
    
    1. 利用isa swizze交换isa指针为NSKVONotifying_<OBJName>
    2. 重写子类的class方法,让其返回值跟原对象一致。
    3. 重写 dealloc, _isKVOA

    参考:一篇讲得比较详细的文章

    这篇值得一读:KVO源码浅析

    相关文章

      网友评论

          本文标题:KVC&KVO

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