MVC
简介
KVC全称Key-Value-Coding ,中文名称为键码编值,可以通过一个key来访问某一个属性。
KVC提供了一种间接访问其属性方法或者成员变量的机制,可以通过字符串来访问对应的属性方法或成员变量。
他是一个非正式的Protrocol ,提供一种机制来间接访问对象的属性,而不是通过调用Setter、Getter方法 访问。KVO就是基于KVC实现的关键技术之一。
KVC常见的用法
常见的API
objectivec
//通过KeyPath(路径)来设值
- (void)setValue:(id)Value forKeyPath:(NSString *)keyPath;
//通过Key来设值
- (void)setValue:(id)Value forKey:(NSString *)key;
//通过keyPath来取值
- (id)valueForkeyPath:(NSString *)keyPath;
//通过Key来取值
- (id)valueForkey:(NSString *)key;
Key与KeyPath
Key
:只能接受当前类所具有的属性,不管是自己的,还是从父类继承过来的。
KeyPath
:除了能接受当前类的属性,还可以接受当前类属性的属性,即可以接受一个关系链。
下面举两个例子来说明:
在上面图片中,我们可以看到常见API的使用方法。
KVC的强大功能
批量存取值功能
批量存值操作:
KVC中,可以根据一组给定的key来获取到一组Value,并且以字典的形式返回。
objectivec
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
批量赋值操作:
//通过该方法允许通过一个字典一次性设置多个属性的值,不需要逐个去使用- (void)setValue:(id)Value forKey:(NSString *)key;
。
objectivec
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;
举例说明:
objectivec
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person* p1 = [[Person alloc] init];
[p1 setValue:@"eric" forKey:@"name"];
[p1 setValue:@"19" forKey:@"age"];
[p1 setValue:@"man" forKey:@"sex"];
NSDictionary* dic = [p1 dictionaryWithValuesForKeys:@[@"name", @"age", @"sex"]];
NSLog(@"%@", dic);
NSDictionary* dic1 = @{@"name":@"jack", @"age":@30, @"sex":@"women"};
Person* p2 = [[Person alloc] init];
[p2 setValuesForKeysWithDictionary:dic1];
NSLog(@"name = %@, age = %@, sex = %@", p2.name, p2.age, p2.sex);
}
return 0;
}
打印结果:
字典转化模型
如果model
和dic
不匹配,可以重写方法-(void)setValue:(id)value forUndefinedKey:(NSString *)key
.
objectivec
#import "Person.h"
@implementation Person
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
if([key isEqualToString:@"sex"]) {
self.sex = (NSString*) value;
}
}
@end
KVC的底层原理
赋值原理
结合上图,来看看KVC赋值的原理:
- 首先会查找
setKey
、_setKey
方法,如果找到,那么直接调用方法赋值。 - 如果没有找到方法,则会查看
+ (BOOL)accessInstanceVariablesDirectly
(控制是否可以直接访问实例变量)是否为YES(默认为YES)。 - 若为YES,则会按照
_key
,_isKey
,key
,isKey
的顺序查找成员变量,如果找到则会直接给成员变量赋值,找不到就抛出NSUnknownException
异常。 - 若为NO,则会调用
setValue:ForUndefinedKey:
并且抛出NSUnknownException
异常。
取值原理
结合上图,来看看KVC取值的原理:
- 首先会按照
getKey
,key
,isKey
,_key
的混序查找方法,如果找到方法,直接调用方法。 - 若未找到方法,则查看
+ (BOOL)accessInstanceVariablesDirectly
(控制是否可以直接访问实例变量)是否为YES(默认为YES)。 - 若返回为YES,则按照
_key
,_isKey
,key
,isKey
的顺序去查找成员变量,如果找到成员变量,则直接取值,未找到则抛出NSUnknownException
异常。 - 若为NO,则会调用
valueForundefinedKey:
并且抛出NSUnknownException
异常。