美文网首页
KVO 原理

KVO 原理

作者: js_huh | 来源:发表于2020-07-17 19:39 被阅读0次

基本原理

  • 被观察者对象为A时,
    KVO会为被观察者对象A, 动态创建当前类的子类,
    并为这新创建的子类,重写KeyPath的setter方法
    setter方法负责通知观察者,属性的改变状况

深入解析

  • Apple 使用了isa来实现 KVO 。
  • 当被观察对象为A时,KVO机制动态创建一个新的名为: NSKVONotifying_A的新类,该类继承自对象A的本类。
  • 且KVO为NSKVONotifying_A重写观察属性的setter方法
  • setter方法会负责在调用原setter方法之前和之后,通知所有观察者属性值的更改情况。
  • NSKVONotifying_A类剖析:
    在KVO过程中, 被观察对象的isa指针从指向原来的A类,被KVO机制修改为指向系统新创建的子类 NSKVONotifying_A类, 来实现当前类属性值改变的监听;
    示例 :

    XMGWine的真实类是被修改为, NSKVONotifying_XMGWine
    NSKVONotifying_XMGWine是系统创建的中间类。
  • 为什么要有中间类,这样做的好处 ?
    • 当对象注册为观察者时,isa指针指向被观察者的新子类,那么这个被观察的对象就神奇地变成新子类的对象或实例了。
    • 因而在被观察者对象上对setter的调用就会调用已重写的setter,从而激活键值通知机制。
    • 从而来实现对"被观察者"的"类属性值"改变的监听 !
  • 子类setter方法剖析:
    • KVO的键值观察依赖于NSObject的两个方法:willChangeValueForKey:didChangevlueForKey:
      • willChangeValueForKey:
        被观察属性发生改变之前,调用此方法,通知系统该keyPath即将改变。
        - (void)willChangeValueForKey:(NSString *)key;
      • didChangevlueForKey:
        被观察属性发生改变之后,调用此方法,通知系统该keyPath的属性值已经变更。
        - (void)didChangeValueForKey:(NSString *)key;
    • 之后observeValueForKey:ofObject:change:context:方法被调用,且重写被观察者属性的setter方法,这种继承方式的注入是在运行时而不是编译时实现的。
      • KVO为子类"被观察者的属性",重写setter的工作原理在代码中相当于:
        -(void)setName:(NSString *)newName{
         [self willChangeValueForKey:@"name"]; -- KVO在调用存取方法之前总调用
          -- 调用父类的存取方法
          -- KVC, 给对应属性'name',赋予新值'newName'.
         [super setValue:newName forKey:@"name"]; 
         [self didChangeValueForKey:@"name"]; -- KVO在调用存取方法之后总调用
      }
      
      • 注意:
        • 只有遵循 KVO 变更属性值的方式,才会执行KVO的回调方法
        • 如果赋值没有通过setter方法,而是直接修改属性对应的成员变量。
          例如: 仅调用_name = @"newName",这时是不会触发KVO机制

备注:

  • isa : 混写(isa-swizzling)
    isa:is a kind of ; swizzling:混合,搅合;
  • keyPath: "被观察者"里面的属性
    需要监听其属性值变化的属性。

也可以看看

相关文章

网友评论

      本文标题:KVO 原理

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