探寻KVO & KVC

KVO

KVO的本质是什么?

KVO的全称是Key-Value Observing,可以用于监听某个对象属性值的改变。
主要使用下面几个方法:

- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSKeyValueChangeKey, id> *)change context:(nullable void *)context;
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

我们自定义一个Person对象,我们通过给Person对象添加KVO监听,来观察添加KVO前后的变化,见下图:


image.png

从打印结果我们可以看到:

  • person1的类对象改变成了NSKVONotifying_Person
  • 通过输出方法的地址,我们发现添加KVO之后,实际调用的是Foundation _NSSetIntValueAndNotify
    image.png

下图是KVO实现的伪代码

image.png

我们发现,当对象通过KVO监听属性变化时,会利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类
当修改instance对象的属性时,

  • 会调用Foundation的_NSSetXXXValueAndNotify函数
  • willChangeValueForKey:
  • 父类原来的setter
  • didChangeValueForKey:内部会触发监听器(Oberser)的监听方法( observeValueForKeyPath:ofObject:change:context:

如何手动触发KVO?

手动调用willChangeValueForKey:didChangeValueForKey:

直接修改成员变量会触发KVO么?

不会触发KVO

KVC

KVC的全称是Key-Value Coding,俗称“键值编码”,可以通过一个key来访问某个属性,常见的API如下:

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key; 
image.png
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。