本文主要是介绍iOS底层原理探究之----KVC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
不管是平常开发还是找工作面试中,KVC、KVO的原理都是面试官比较喜欢问的问题。最近抽时间研究了一下KVC和KVO的实现原理,本想着一篇文章就可以说完,等研究完才发现不看不知道,一看吓一跳。KVC和KVO都有很多内容可以研究,所以分为两篇分享,第一篇分享KVC的底层原理。
本次分享准备从这几个方面入手:
1、概念定义
2、原理介绍
3、自己实现
4、使用场景
一、概念定义
KVC:Key-value coding (键-值编码)
苹果开发者文档中有这么一句话:
大意就是要想理解KVO必须首先理解KVC!足可见KVC的重要性。
概念:允许开发者通过key直接访问对象的属性方法或者成员变量,而不需要调用明确的存取方法。
实际上,KVC是对NSObject的扩展:NSKeyValueCoding,当然其中对NSArray、NSDictionary、NSMutableDictionary、NSOrderedSet、NSSet也添加了扩展,更方便使用。
其中主要提供了以下四个方法,当然还有很多其他方法,可以在苹果文档中查看:
- (nullable id)valueForKey:(NSString *)key;
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKeyPath:(NSString *)keyPath;
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
这些也是我们平常使用KVC使用最多的方法。
二、原理介绍
不知道大家在平常使用KVC的时候有没有思考这些问题:
Q1:不管是set还是get,只需要传入一个key字符串就可以存取,为什么?
Q2:如果类中没有相应的属性是否一定不能存取?
带着这样的问题我们研究一下KVC的实现原理。通过查阅苹果的官方文档和介绍,我们就可以了解到,在我们看似简单的API调用下,苹果其实是有一套完整的搜索规则,我们分set和get分别说明如下:
setValue:(id)value forKey:(NSString *)key
- set的搜索规则如下
1.查找set<Key>:或_set<Key>命名的setter,按照这个顺序,如果找到的话,调用这个方法并将值传进去(根据需要进行对象转换)。
2.如果没有发现一个简单的setter,但是accessInstanceVariablesDirectly类属性返回YES,则查找一个命名规则为_<key>、_is<Key>、<key>、is<Key>的实例变量。根据这个顺序,如果发现则将value赋值给实例变量。
3.如果没有发现setter或实例变量,则调用setValue:forUndefinedKey:方法,并默认提出一个异常,但是一个NSObject的子类可以提出合适的行为。
上面提到了一个类属性accessInstanceVariablesDirectly
+ (BOOL)accessInstanceVariablesDirectly
它表示是否允许读取实例变量的值,如果为YES则在KVC查找的过程中,从内存中读取属性、实例变量的值。如果不允许外界通过KVC对我们的私有属性和成员变量进行操作,则可以设置此值为NO。
set的规则相对比较简单,相信大家都能看懂。我们也可以按照这个搜索顺序自己验证是否符合。(实现两个setter方法以及添加四种成员变量,然后依次注释掉后检查是不是按照上面的顺序进行赋值操作。)
- get的搜索规则
get的搜索规则相对于set就有点复杂了
1.通过getter方法搜索实例,例如get<Key>, <key>, is<Key>, _<key>的拼接方案。按照这个顺序,如果发现符合的方法,就调用对应的方法并拿着结果跳转到第五步。否则,就继续到下一步。
2.如果没有找到简单的getter方法,则搜索其匹配模式的方法countOf<Ke
这篇关于iOS底层原理探究之----KVC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!