-
一、KVC定义
KVC
:(NSKeyValueCoding)
键值编码,一个非正式Protocol
启用的一种机制,对象采用这种机制来提供对其属性的间接访问,这种间接访问机制补充了实例变量及其关联的访问器方法提供的直接访问。
-
二、使用场景
- 访问私有成员变量:我们知道当属性定义在.h文件里的时候,我们是能够通过属性来访问的。但是如果是定义在.m文件里,那么我们就无法直接访问到了,这时如果知道私有成员变量名,就可以通过
KVC
就可以进行访问了 - 简化字典转模型代码:可以使用
setValuesForKeysWithDictionary
简单的一步就把字典里的每一项赋值给你实体类对应的属性。
- 访问私有成员变量:我们知道当属性定义在.h文件里的时候,我们是能够通过属性来访问的。但是如果是定义在.m文件里,那么我们就无法直接访问到了,这时如果知道私有成员变量名,就可以通过
-
三、KVC常见API
- (nullable id)valueForKey:(NSString *)key;
//直接通过Key来取值
- (void)setValue:(nullable id)value forKey:(NSString *)key;
//通过Key来设值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
//通过KeyPath来取值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
//通过KeyPath来设值
+ (BOOL)accessInstanceVariablesDirectly;
//表示是否可以直接访问成员变量,默认返回YES,返回YES:会按照`setKey:`、`_setKey:`的顺序直接访问实例变量,如果没有,会按照`_key`、`_isKey`、`key`、`iskey`的顺序查找成员变量的顺序搜索成员变量,没有找到抛出异常。返回NO:会按照`setKey`、`_setKey`的顺序直接访问实例变量,没有找到抛出异常。
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//如果指定的键对应于接收setter调用的对象所不具有的属性,则该对象向自身发送setValue:forUndefinedKey:消息
- (nullable id)valueForUndefinedKey:(NSString *)key;
//如果指定的键对应于接收getter调用的对象所不具有的属性,则该对象向自身发送valueForUndefinedKey:消息
-
四、setValue: forKey:赋值流程
- 1).按
setKey:
、_setKey
的顺序进行查找 - 2).找到赋值,没找到,查看
accessInstanceVariablesDirectly
的返回,返回NO
,调用setValue: forUndefinedKey:
进行处理。返回YES
,进入下一步。 - 3).按照
_key
、_isKey
、key
、iskey
的顺序查找成员变量。找到赋值,否者报错。
- 1).按
代码示例:
#import "MMKVCPerson.h"
@interface MMKVCPerson (){
// 成员变量`_key`、`_isKey`、`key`、`iskey`
// NSString *_name;
// NSString *_isName;
// NSString *name;
// NSString *isName;
}
@end
@implementation MMKVCPerson
//1.setKey
- (void)setName:(NSString *)name{
NSLog(@"setKey: Value-%@",name);
}
//2._setKey
- (void)_setName:(NSString *)name{
NSLog(@"_setKey: Value-%@",name);
}
//表示是否可以直接访问成员变量,默认返回YES,返回YES:会按照`setKey:`、`_setKey:`的顺序直接访问实例变量,如果没有,会按照`_key`、`_isKey`、`key`、`iskey`的顺序查找成员变量的顺序搜索成员变量,没有找到抛出异常。返回NO:会按照`setKey`、`_setKey`的顺序直接访问实例变量,没有找到抛出异常。
+ (BOOL)accessInstanceVariablesDirectly {
return YES;
}
//如果指定的键对应于接收setter调用的对象所不具有的属性,则该对象向自身发送setValue:forUndefinedKey:消息
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
NSLog(@"找不到由%@命名的属性",key);
}
setValue: forKey:赋值流程图:
-
五、valueForKey:访问流程
- 1).按照 getKey、key、iskey、_key 顺序查找方法
- 2).存在取值,不存在,查看
accessInstanceVariablesDirectly
的返回,返回NO
,调用valueForUndefinedKey:
进行处理。返回YES
,进入下一步。 - 3).按照
_key
、_isKey
、key
、iskey
的顺序查找成员变量。找到取值,否者报错。 代码示例:
#import "MMKVCPerson.h"
@interface MMKVCPerson ()
{
// 成员变量`_key`、`_isKey`、`key`、`iskey`
NSString *_name;
NSString *_isName;
NSString *name;
NSString *isName;
}
@end
@implementation MMKVCPerson
- (NSString *)getName{
return @"getKey";
}
- (NSString *)name{
return @"key";
}
- (NSString *)isName{
return @"isKey";
}
- (NSString *)_name{
return @"_Key";
}
+ (BOOL)accessInstanceVariablesDirectly {
return YES;
}
- (id)valueForUndefinedKey:(NSString *)key {
NSLog(@"找不到由%@命名的属性",key);
return nil;
}
valueForKey:访问流程图: