前言
在 OC 的学习过程中,KVO 和 KVC 是我们经常提到的。我一直没有很清楚的搞明白 KVC 是个啥。今天开看一下。
KVO & KVC
- KVO 其实就是键值监听,用于监听对象值的改变。方便做一些和值相关的一些处理。
- KVC 其实是键值编码,很多时候用于不知道具体的对象类型,但是知道它的属性名,甚至对象类型和属性名都不知道。需要对这个可能存在的属性做操作(赋值或取值)
KVO
OC 中的 KVO 机制常用于实现类的监听,在被监听的值改变的时候可以自动调用监听方法,用于解耦。
如果一个类被添加了KVO监听,则会自动把该类对象改为NSKVONotifying_XXX类,NSKVONotifying_XXX类是通过runtime创建的XXX类的子类。
KVO本质
-
利用
runtime动态生成一个子类(NSKVONotifying_XXX),并且让instance对象的isa指向这个全新的子类 -
当修改
instance对象的属性的时候,会调用Foundation的_NSSeetXXXValueAndNotify函数 -
方法调用流程:
willChangeValueForKey:- 父类原来的setter方法
didChanageValueForKey:- 内部触发监听器
(Oberser)的监听方法:oberserValueForKeyPath:ofObject:change:context:
-
手动触发监听器:
- 手动顺序调用
willChangeValueForKey:、didChanageValueForKey:方法。
- 手动顺序调用
-
NSKVONotifying_XXX 生成的方法:
-
setXX内部调用Foundation的_NSSeetXXXValueAndNotify函数 -
class返回原来的类,隐藏NSKVONotifying_XXX类 dealloc_isKVOA
-
如果要触发KVO机制,必须调用到set方法,如果使用直接复制的方式,则无法触发KVO
KVC
KVC 是 key-value-coding 的简称,是OC的特性之一.
常用API:
- -(void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- -(void)setValue:(id)value forKey:(NSString *)key;
- -(id)valueForKey:(NSString *)key;
- -(id)valueForKeyPath:(NSString *)keyPath;
key 和 keyPath 的区别是,keyPath是多层级的,a.b.c 的方式来访问属性,key为当前层级,不可以访问子级。
KVC 原理
调用-(void)setValue:(id)value forKey:(NSString *)key的时候, 方法调用流程:
- setKey:
- _setKey:
- accessInstanceVariablesDirectly 这方法如果返回YES,跳转到第4步,如果返回NO,跳转到第5步
- 依次查找 _key、_isKey、key、isKey 如果找到了则直接赋值,如果没有找到,跳转到第5步
- 调用
setValue:forUndefinedKey:
setValueForKey.png
调用-(id)valueForKey:(NSString *)key的时候, 方法调用流程:
- 依次调用
getkey、key、isKey、_key方法如果存在则直接返回,如果不存在则跳转到第2步 - accessInstanceVariablesDirectly 这方法如果返回YES,跳转到第3步,如果返回NO,跳转到第4步
- 依次查找 _key、_isKey、key、isKey 如果找到了则直接赋值,如果没有找到,跳转到第4步
- 调用
valueForUndefinedKey:
valueForKey.png
最后
以上就是本篇的内容,势必会有一些遗漏和错误,欢迎斧正~











网友评论