KVO相关

129 阅读1分钟

KVO的实现

  • KVO是观察者模式的具体实现方式之一,观察者模式自身实现了不对观察对象的浸入,能够比较好的实现解耦

  • KVO的基本原理

    1. 使用了isa-swizzing的技术,是一种一对一的关系
      KVO.png
    2. 自动实现
      1. 在观察对象X的时候,运行时系统会新建一个NSKVONotifying_X的子类, 并且重写子类的setter方法;直接调用class方法依旧显示X的类名
    - (void)setValue:(id)value {
         [self willChangeValueForKey:@"value"];
         [super setValue:value];
         [self didChangeValueForKey:@"value"];
     }
    

    直接赋值成员变量,由于不会调用setter方法,并不会触发KVO

    1. 手动实现

      1. 需要在setter方法中实现willchangeValue、didchangeValue方法
      2. 需要配合+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key的实现
    2. KVO在子类中的问题:需要定义static const常量,才能保证子类、父类都能安全的观察同样的键值而不会冲突

    3. 一般不推荐KVO和多线程混起来,更不应该在他们相互之间用KVO,KVO对观察者改变所作出的响应是在发出通知的线程上发生的,NSNOtification也是

    4. KVO的实现离不开KVC,KVC的查找过程

    • 执行过程如下:
      1. 会优先调用set<Key>属性方法,这个是标准的setter方法,要符合KVC的命名规则

      属性若为testA,则setter方法为setTestA:(id)testA,成员变量为_testA,若为TestB,则为setTestB:(id)TestB,_TestB

      1. 没找到的情况下,会调用+(BOOL)accessInstanceVariablesDirectly方法,该方法会默认返回Yes,FOundation就会按照_、_is、、is的顺序查找实例变量是否存在
    1. KVV键值验证 1.- (BOOL)validateName:(NSString **)nameP error:(NSError * __autoreleasing *)error 一般可以在这个方法里做些特殊处理