KVC简介
KVC(Key-value coding)键值编码,就是指iOS的开发中,可以允许开发者通过Key名间接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。这样就可以在运行时动态在访问和修改对象的属性,而不是在编译时确定。
KVC提供了一种间接访问属性方法或成员变量的机制,可以通过字符串来访问对象的的属性方法或成员变量。
在实现了访问器方法的类中,使用点语法和KVC访问对象其实差别不大,二者可以任意混用(因为KVC会首先搜索访问器方法,见下文)。但是没有访问器方法的类中,点语法无法使用,这时KVC就有优势了。
KVC和KVO都是基于OC的动态特性和Runtime机制的。
KVC重要的四个方法
// 直接通过Key来取值
- (nullable id)valueForKey:(NSString *)key;
// 通过Key来设值
- (void)setValue:(nullable id)value forKey:(NSString *)key;
// 通过KeyPath来取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
// 通过KeyPath来设值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
keyPath方法,用来进行深层访问(key使用点语法),也可单层访问
#import <Foundation/Foundation.h>
@interface Birthday : NSObject
@property (copy, nonatomic) NSString *year;
@property (copy, nonatomic) NSString *month;
@property (copy, nonatomic) NSString *day;
@end
#import <Foundation/Foundation.h>
#import "Birthday.h"
@interface Person : NSObject
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) NSInteger *sex;
@property (strong, nonatomic) NSNumber *age;
@property (strong, nonatomic) Birthday *birthday;
@end
- (void)viewDidLoad {
[super viewDidLoad];
Person *myself = [[Person alloc] init];
[myself setValue:@"sakura" forKey:@"name"];
NSLog(@"-------name = %@",[myself valueForKey:@"name"]);
/**
keyPath的setter方法:setValue: forKeyPath:
keyPath的getter方法:valueForKeyPath:
keyPath为多级访问,使用点语法
*/
//注意,这里要想使用keypath对adress的属性进行赋值,必须先给myself赋一个Address对象
Birthday *myBirthday = [[Birthday alloc] init];
[myself setValue:myBirthday forKey:@"Birthday"];
//KeyPath为多级访问
[myself setValue:@"1993" forKeyPath:@"birthday.year"];
NSLog(@"-------year = %@",[myself valueForKeyPath:@"birthday.year"]);
}
keypath除了对当前对象的属性进行赋值外,还可以对其更“深层”的对象进行访问。
keypath可以访问到array数组中所有存储的对象的属性,前提是对象类型是一样的。
NSArray *names = [array valueForKeyPath:@"name"];
通过valueForKeyPath:将数组中所有对象的name属性值取出,并放入一个数组中返回。
KVC 的多值操作
批量取值操作
KVC还有更强大的功能,可以根据给定的一组key,获取到一组value,并且以字典的形式返回。
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;
批量赋值操作
同样,也可以通过KVC进行批量赋值。使用对象调用setValuesForKeysWithDictionary:方法时,可以传入一个包含key、value的字典进去,KVC可以将所有数据按照属性名和字典的key进行匹配,并将value给User对象的属性赋值。
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;
使用 KVC 进行字典转模型
json数据中修改字段名称修改映射
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
if ([key isEqualToString:@"Age"]) {
[self setValue:value forKey:@"age"];
}
}
- Json里的字段数量和字段名字应该和model类所匹配,Json少了字段不会出现问题,但是多了或者是字段名不对,就会崩溃。
- 不需对基本数据类型做处理,例如int型转NSNumber,内部会自动作出处理
- NSArray和NSDictionary等集合对象,value都不能是nil,否则会导致Crash
异常信息和异常处理
当根据KVC搜索规则,没有搜索到对应的key或者keyPath,则会调用对应的异常方法。异常方法的默认实现,在异常发生时会抛出一个NSUndefinedKeyException的异常,并且应用程序Crash。
网友评论