KVC、KVO原理

一、Key-Value Coding: 键值编码 (KVC)

方法调用:

// 对象属性 
// 类似: Person -> name
setValue: forKey:
// 对象的属性或者 属性的属性...... 可见它已经包含前者. 
// 类似: Person -> car -> name
setValue: forKeyPath:
// 字典转模型 (key,属性一一对应)
setValuesForKeysWithDictionary:

KVC主要通过isa-swizzling, 来实现其内部查找定位的. 默认的实现方法由NSOject提供

[object setValue:@"134567" forKey:@"uid"];
编译器处理:
// 首先找到对应sel
SEL sel = sel_get_uid("setValue:forKey:");
// 根据object->isa找到sel对应的IMP实现指针
IMP method = objc_msg_lookup (object->isa,sel);
// 调用指针完成KVC赋值
method(object, sel, @"134567", @"uid");
KVC键值查找原理

setValue:forKey:搜索方式

1、首先搜索setKey:方法.(key指成员变量名, 首字母大写) 
2、上面的setter方法没找到, 如果类方法accessInstanceVariablesDirectly返回YES. 
那么按 _key, _isKey,key, iskey的顺序搜索成员名.(NSKeyValueCodingCatogery中实现的类方法, 
默认实现为返回YES) 
3、如果没有找到成员变量, 调用setValue:forUnderfinedKey:

valueForKey:的搜索方式

1、首先按getKey, key, isKey的顺序查找getter方法, 找到直接调用. 
如果是BOOL、int等内建值类型, 会做NSNumber的转换. 
2、上面的getter没找到, 查找countOfKey, objectInKeyAtindex, KeyAtindexes格式的方法.
 如果countOfKey和另外两个方法中的一个找到, 
那么就会返回一个可以响应NSArray所有方法的代理集合的NSArray消息方法. 
3、还没找到, 查找countOfKey, enumeratorOfKey, memberOfKey格式的方法. 如果这三个方法都找到, 
那么就返回一个可以响应NSSet所有方法的代理集合. 
4、还是没找到, 如果类方法accessInstanceVariablesDirectly返回YES. 那么按 _key, _isKey, key, iskey的顺序搜索成员名. 
5、再没找到, 调用valueForUndefinedKey.

二、Key-Value Observing 键值观察(KVO)

KVO是基于KVC实现的,使用方法:

// 1.添加一个观察者
[self.object addObserver:self forKeyPath:@"uid" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];

// 2.观察者监听到之后回调方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
}
// 3.移除观察者, 类在销毁前需要销毁
[self.object removeObserver:self forKeyPath:@"uid"];

KVO底层实现:
当一个类的属性被观察的时候,系统会通过runtime动态的创建一个该类的派生类NSKVONotifying_xx,并且会在这个类中重写基类被观察的属性的setter方法,而且系统将这个类的isa指针指向了派生类,从而实现了给监听的属性赋值时调用的是派生类的setter方法。重写的setter方法会在调用原setter方法前后,通知观察对象值得改变。


KVC、KVO原理_第1张图片
KVO原理

参考文章:
KVC,KVO实现原理

你可能感兴趣的:(KVC、KVO原理)