美文网首页
KVO 的本质?

KVO 的本质?

作者: 游城十代2dai | 来源:发表于2020-04-07 13:49 被阅读0次
  1. iOS 用什么方式实现对一个对象的 KVO ? (KVO 的本质是什么?)
  • 首先利用 Runtime API 动态创建一个中间类(NSKVONotifying_ + 类名), 并让实例对象的 isa 指针指向这个中间类, 当修改实例对象的属性时, 会调用 Foundation 的 _NSSetxxxValueAndNotify 函数, 该函数内部主要是做 willChangeValueForKey, super 的 setter, didChangeValueForKey, 然后会触发 Observer 监听方法
  1. 如何手动触发 KVO?
  • 实例对象先调用 willChangeValueForKey, 然后再调用 didChangeValueForKey
  1. KVO 是否可以添加成员变量的观察?
  • 可以的, 为成员变量添加 KVO 是可以的但是必须用 KVC 方式赋值

具体观察代码, 重点observeValueForKeyPath:

#import "ViewController.h"
#import "Person.h"
#import <objc/runtime.h>

/**
 * 1. iOS 用什么方式实现对一个对象的 KVO ? (KVO 的本质是什么?)
 * 首先利用 Runtime API 动态创建一个中间类(NSKVONotifying_ + 类名), 并让实例对象的 isa 指针指向这个中间类, 当修改实例对象的属性时, 会调用 Foundation 的 _NSSetxxxValueAndNotify 函数, 该函数内部主要是做 willChangeValueForKey, super 的 setter, didChangeValueForKey, 然后会触发 Observer 监听方法
 * 2. 如何手动触发 KVO?
 * 实例对象先调用 willChangeValueForKey, 然后再调用 didChangeValueForKey
 */

@interface ViewController ()

@property (nonatomic, strong) Person *person1;
@property (nonatomic, strong) Person *person2;
@end

@implementation ViewController


- (void)dealloc {
    [self.person1 removeObserver:self forKeyPath:@"age"];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.person1 = Person.new;
    self.person1.age = 10;
    self.person2 = Person.new;
    self.person2.age = 20;
    
    // 添加监听
    [self.person1 addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    self.person1.age = arc4random() % 100 + 1;
    self.person2.age = arc4random() % 100 + 1;
}

// 当监听对象的属性值改变时, 就会调用
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    /**
     * 打印 person1 的类对象
     * (lldb) p self.person1.isa
     * (Class) $2 = NSKVONotifying_Person
     * Fix-it applied, fixed expression was:
     * self.person1->isa
     *
     * 打印 person2 的类对象
     * (lldb) p self.person2.isa
     * (Class) $3 = Person
     * Fix-it applied, fixed expression was:
     * self.person2->isa
     *
     * 打印所有方法, 可以 llbd 也可以自己实现一个 _printMethodNamesOfClass
     * (lldb) po [$2 _shortMethodDescription]
     * <NSKVONotifying_Person: 0x600000d40870>:
     * in NSKVONotifying_Person:
     *   Instance Methods:
     *      - (void) setAge:(long)arg1; (0x7fff258e518d)        //  ----- 实际会先调用 _NSSetIntValueAndNotify
     *      - (Class) class; (0x7fff258e2fd5)           //  ----- 重写 class 实现, class 方法 底层可能就是 object_getClass, 重写后让读者认为还是 Person 类
     *      - (void) dealloc; (0x7fff258e2d3a)      // ---- 收尾工作
     *      - (BOOL) _isKVOA; (0x7fff258e2d32)
     *   in Person:
     *      Properties:
     *          @property (nonatomic) long age;  (@synthesize age = _age;)
     *      Instance Methods:
     *          - (long) age; (0x10e795f90)
     *          - (void) setAge:(long)arg1; (0x10e795fb0)
     *   (NSObject ...)
     */

    [self _printMethodNamesOfClass:object_getClass(object)];
    NSLog(@"%@", change);
}

// 打印所有方法
- (void)_printMethodNamesOfClass:(Class)cls {
    // 定义
    unsigned int outCount = 0;
    Method *methodList = NULL;
    Method tempMethod = NULL;
    NSMutableString *strResult = [NSMutableString string];
    NSString *strTemp = [NSString string];
    
    // copy 出方法列表
    methodList = class_copyMethodList(cls, &outCount);
    
    // 遍历
    for (int i = 0; i < outCount; ++i) {
        tempMethod = methodList[i];
        strTemp = NSStringFromSelector(method_getName(tempMethod));
        [strResult appendFormat:@"\n%@", strTemp];
    }
    
    NSLog(@"%@", strResult);
}


@end

相关文章

  • Objective-C的本质(4)—— KVO本质

    参考:iOS底层原理总结 - 探寻KVO本质iOS-KVO本质 问题一:kvo如果找到对应的属性 KVO不存在查找...

  • iOS原理篇(一): KVO实现原理

    KVO实现原理 什么是 KVO KVO 基本使用 KVO 的本质 总结 一 、 什么是KVO KVO(Key-Va...

  • 深入理解KVO

    iOS | KVO | Objective-C KVO的本质是什么,如何手动触发KVO? 1.什么是KVO KVO...

  • 04. KVO使用,原理,本质

    问题 KVO日常使用 KVO原理(KVO本质是什么) 如何手动触发KVO 直接修改成员变量会触发KVO吗 KVO图...

  • KVO

    0:KVO的使用步骤 1:KVO本质 methodForSelector方法 NSKVONotifying_Per...

  • 探索中的KVO

    探索KVO的本质 什么是KVO KVO的全称就是Key-Value Observing ,俗称“键值监听”。用于监...

  • iOS KVO

    什么是KVO KVO俗称“键值监听”,用来监听某个对象属性值的改变 KVO的使用 KVO 本质 在给某个对象添加K...

  • iOS-KVO本质

    参考篇:iOS-KVO浅谈 前言:本文简述KVO本质,如有错误请留言指正。 什么是KVO? KVO的全称是Key-...

  • 03-OC中KVO的底层原理

    KVO本质 什么是KVO? KVO:Key-Value Observing,用来监听类的某个对象的某个属性的值发生...

  • 小码哥底层原理笔记:KVO的本质

    使用KVO主要是监听属性的变化。简单的KVO如下: KVO的本质 当我们给person1增加KVO后修改age的值...

网友评论

      本文标题:KVO 的本质?

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