KVO和KVC

作者: 恋家的人走不丢 | 来源:发表于2022-08-30 16:21 被阅读0次
    全称
    • KVO: Key-Value-Observer
    • KVC: Key-Value-Coding

    KVO的使用

    使用过程
    • 监听回调返回新值和旧值
      NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;

    • 添加监听
      [被监听的实例对象 addObserver:监听器 forKeyPath:属性 options:options context:nil]

    • 监听接收事件
      - (void)observeValueForKeyPath:(NSString*)keyPathofObject:(id)objectchange:(NSDictionaryid> *)changecontext:(void*)context{ NSLog(@"%@--%@--%@",object,keyPath,change); }

    • 记得添加监听和移除监听,需要配对使用

    原理

    测试类 Person

    1. 系统会生成NSKVONotifying_Person类,该类继承Person,并且将Person的isa指向NSKVONotifying_Person。

    2. NSKVONotifying_Person从写监控属性的setter方法,内部调用_assetXXXValueAndNotify();
      _assetXXXValueAndNotify内部实现:

      2.1 - (void)willChangeValueForKey:(NSString *)key;

      2.2- (void)didChangeValueForKey:(NSString *)key;

      2.3 didChangeValueForKey里面调用 [super didChangeValueForKey]时,会触发回调方法
      - (void)observeValueForKeyPath:(NSString*)keyPathofObject: (id)objectchange:(NSDictionaryid> *)changecontext:(void*)context

      通知开发者数据发生变化。

    3.NSKVONotifying_Person内部还会从写 - (Class)class; 方法,目的是隐藏系统生成的类。

    4.如果需要手动调用,只需要调用2个方法:
    willChangeValueForKey
    didChangeValueForKey
    即可;
    5.单纯使用KVO,访问成员变量person -> age = 10;是不会触发KVO监听的。

    KVC setValueForKey: 和setValueForKeyPath:

    假如Person对象有个属性叫age

    setValueForKey
    • 可以对实例对象的某个属性赋值
    setValueForKeyPath:入参是路径,
    • 可以对实例对象中的,某个对象的某个属性,进行赋值;例如入参可以是:person.data.num,就代表对person对象的data对象的num属性进行赋值

    • 可以访问对象的隐藏属性

    • 可以求最大最小值,再也不用手动遍历数组求值了

      求最大值:[array valueForKeyPath:@"@max.self"]

    使用KVC赋值

    例如Person中有一个age属性

    • 查找顺序
      1.setAge:
      2._setAge:

    • 假如上面2个方法都没有实现,则系统会调用是否允许直接访问成员变量方法:
      + (BOOL)accessInstanceVariablesDirectly
      如果返回NO,则系统调用setValue:forUndefineKey,直接报NSUnknowKeyException异常;

    • 如果没有setter方法,只有成员变量时,并且+ (BOOL)accessInstanceVariablesDirectly返回YES,KVO同样可以监测到属性值发生了改变;
      例如需要查找的属性叫age,则查找顺序如下

      1. _age
      2. _isAge
      3. age
      4. isAge
    

    如果方法未找到,上面4个属性也未找到,则会报上面的异常setValue:forUndefineKey

    KVC取值 valueForKey: 和valueForKeyPath:

    • 方法查找顺序
      1. getKey
      2. key
      3. isKey
      4. _key
    

    如果方法未找到,则会调用系统方法+ (BOOL)accessInstanceVariablesDirectly判断是否可以直接访问成员变量,如果是NO,则会报valueForUndefineKey,如果是YES,则会按如下顺序查找成员变量:

      1. _key
      2. _isKey
      3. key
      4. isKey
    

    相关文章

      网友评论

          本文标题:KVO和KVC

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