KVC
?KVC是Key-Value Coding
的简称,称为键值编码
。它是NSKeyValueCoding
非正式协议启用的一种机制,可使对象经过该协议来间接访问其属性
,这种间接访问机制补充了实例变量及其相关的访问器方法所提供的直接访问。html
//经过setValue中key来设值
- (void)setValue:(nullable id)value forKey:(NSString *)key;
//经过valueForKey中key来取值
- (nullable id)valueForKey:(NSString *)key;
//经过valueForKeyPath中keyPath来设置值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
//keyPath来取值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
复制代码
效果以下markdown
//默认返回YES,表示若是没有找到Set<Key>方法的话,会按照_key,_iskey,key,iskey的顺序搜索成员,设置成NO就不这样搜索
+ (BOOL)accessInstanceVariablesDirectly;
//KVC提供属性值正确性验证的API,它能够用来检查set的值是否正确、为不正确的值作一个替换值或者拒绝设置新值并返回错误缘由。
- (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
//这是集合操做的API,里面还有一系列这样的API,若是属性是一个NSMutableArray,那么能够用这个方法来返回。
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;
//若是Key不存在,且KVC没法搜索到任何和Key有关的字段或者属性,则会调用这个方法,默认是抛出异常。
- (nullable id)valueForUndefinedKey:(NSString *)key;
//和上一个方法同样,但这个方法是设值。
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//若是你在SetValue方法时面给Value传nil,则会调用这个方法
- (void)setNilValueForKey:(NSString *)key;
//输入一组key,返回该组key对应的Value,再转成字典返回,用于将Model转到字典。
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
复制代码
上面咱们讲到了KVC
一些常见的API,那么在设置值以及取值
中,iOS底层到底作了什么呢?从代码上咱们看到这些
API
是Foundation
框架下的,因为Foundation
是不开源的,所以咱们没法经过源码查看底层到底是如何实现的。可是咱们能够经过苹果官方文档
来查看。查看苹果相关文档 Key-Value Coding Programming Guideapp
咱们从官方文档中能够得知,当咱们经过setValue:forKey:
来设置值的时候,步骤以下框架
步骤一
:首先找这三种setter:
方法,分别是:set<Key>
->_set<Key>
->setIs<Key>
,其中<Key>
是成员变量的名字,且首字母大写
,好比本文中的name
,顺序就是setName
->_setName
->setIsName
。当找到这三种setter
中任意一个时,则进行赋值,若是没有找到则进入步骤二
.步骤二
:判断+ (BOOL)accessInstanceVariablesDirectly
函数是否返回YES,若是返回YES,则按照 _key
->_iskey
->key
->iskey
的顺序搜索成员,找到任意一个则进行赋值,不然进入步骤三
;若是返回NO,则直接进入步骤三
。步骤三
:若是setter方法 或者 实例变量都没有找到,系统会执行该对象的setValue:forUndefinedKey:
函数,默认抛出异常,因此咱们使用KVC
进行解析模型数据时,要实现setValue:forUndefinedKey:
函数,不然会崩溃。设值总结
当咱们调用valueForKey:
时,内部操做流程以下:ide
步骤一
:调用getter
方法,调用顺序是:get<Key>
-> <key>
-> is<Key>
-> _<key>
,以name为例,getName
-> name
-> isName
-> _name
,若是找到,则直接返回对应的值(多是对象),若是找不到则进入步骤二
步骤二
:判断+ (BOOL)accessInstanceVariablesDirectly
函数是否返回YES,若是为YES,则访问成员变量,顺序为:_<key>
->_is<Key>
-><key>
-> is<Key>
,以name为例则是_name
->_isName
->name
-> isName
,找到则返回对应的值(多是对象),找不到则进入步骤三
;若是返回的是NO,则截止进入步骤三
。步骤三
:均找不到,则调用valueForUndefinedKey:
抛出异常。取值总结
: