本文介绍: KVC的全称是KeyValueCoding,俗称“键值编码”,可以通过一个key访问某个属性;KVC提供了一种间接访问其属性方法成员变量机制可以通过字符串访问对应的属性方法成员变量;它是一个非正式的Protocol,提供一种机制来间接访问对象的属性,而不是通过调用Setter、Getter方法访问。KVO 就是基于 KVC 实现的关键技术之一。

KVC

KVC的全称是KeyValueCoding,俗称“键值编码”,可以通过一个key来访问某个属性;

KVC提供了一种间接访问其属性方法成员变量机制可以通过字符串来访问对应的属性方法或成员变量;

它是一个非正式的Protocol,提供一种机制来间接访问对象的属性,而不是通过调用Setter、Getter方法访问。KVO 就是基于 KVC 实现的关键技术之一。

KVC常用的四种方法
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key;

key和keyPath区别

key:只能接受当前类所具有的属性,不管是自己的,还是父类继承过来的
keypath:除了能接受当前类的属性,还能接受当前类属性的属性,即可以接受关系

用法
        //key的设值取值
        Person *personPath = [[Person alloc] init];
        [personPath setValue:@"I am Father" forKey:@"name"];
        NSLog(@"%@", [personPath valueForKey:@"name"]);

输出结果
在这里插入图片描述

        //keypath的设值取值
        personPath.son = [[PersonSon alloc] init];
        [personPath setValue:@"I am Son" forKeyPath:@"son.sonName"];
        NSLog(@"%@", [personPath valueForKeyPath:@"son.sonName"]);
        NSLog(@"%@", personPath.son.sonName);

输出结果
在这里插入图片描述

批量存值操作

KVC还有更强大的功能可以根据给定一组key获取一组value,并且以字典的形式返回

- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;

批量赋值操作

同样,也可以通过KVC进行批量操作使用对象调用setValuesForKeysWithDictionary:方法时,可以传入一个包keyvalue字典进去,KVC可以将所有数据按照属性名和字典key进行匹配,并将value给对象的属性赋值

- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;

示例代码

        //逐个赋值
        Person *personFirst = [[Person alloc] init];
        [personFirst setValue:@"zxb" forKey:@"name"];
        [personFirst setValue:@20 forKey:@"age"];
        [personFirst setValue:@"男" forKey:@"sex"];
        NSLog(@"name = %@, age = %ld, sex = %@",personFirst.name, (long)personFirst.age, personFirst.sex);
        
        //通过字典赋值取值
        NSDictionary *dictionaryFirst = [personFirst dictionaryWithValuesForKeys:@[@"name", @"age", @"sex"]];
        NSLog(@"dictionaryFirst = %@", dictionaryFirst);
        
        NSDictionary *dictionarySecond = @{@"name":@"zzy", @"age":@11, @"sex":@"女"};
        Person *personSecond = [[Person alloc] init];
        [personSecond setValuesForKeysWithDictionary:dictionarySecond];
        NSLog(@"name = %@, age = %ld, sex = %@",personSecond.name, (long)personSecond.age, personSecond.sex);

输出结果
在这里插入图片描述

字典模型相互转化

如果model属性和dic匹配,可以重写方法-(void)setValue:(id)value forUndefinedKey:(NSString *)key

//StudentModel.h
@interface StudentModel : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *age;
@property (nonatomic, strong) NSString *studentSex;

@end

//StudentModel.m
@implementation StudentModel

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    if ([key isEqualToString:@"sex"]) {
        self.studentSex = (NSString *)value;
    }
}

@end

//main.m
        //字典模型相互转化
        NSDictionary *dictionary = @{@"name":@"stu1", @"age":@66, @"sex":@"nv"};
        StudentModel *model = [[StudentModel alloc] init];
        [model setValuesForKeysWithDictionary:dictionary];
        NSLog(@"model.name:%@",model.name);
        NSLog(@"model.age:%@",model.age);
        NSLog(@"model.sex:%@",model.studentSex);
        
        NSDictionary *tempModelDictionary = [model dictionaryWithValuesForKeys:@[@"name", @"age", @"studentSex"]];
        NSLog(@"tempModelDictionary : %@", tempModelDictionary);

输出结果
在这里插入图片描述

KVC的其他方法

// 默认返回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;

// 使用字典为Model赋值
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;

// 输入一组key,返回该组key对应的Value,再转成字典返回,用于将Model转到字典。
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;

KVC原理探索

setValue:forKey:原理(KVC赋值原理

请添加图片描述

这里提到了setValue:forUndefinedKey方法,这个方法怎么用呢?

在 iOS 的 KVC(键-值编码)中,如果调用了一个对象的 setValue:forKey: 方法,但是这个对象并没有对应的属性或者实例变量来存储这个值,那么就会触发这个对象的 setValue:forUndefinedKey: 方法。这个方法的作用就是在运行动态地为这个对象添加新的属性或者实例变量,并将这个值存储到新添加的属性或实例变量中。
需要注意的是,如果一个类没有实现 setValue:forUndefinedKey: 方法,那么默认抛出一个异常。因此,如果你在使用 KVC 的时候发现程序崩溃了,并且错误信息包含 “NSUnknownKeyException” 这个字符串,那么很可能就是因为这个原因

valueForKey:的原理(KVC取值原理)

注意事项

原文地址:https://blog.csdn.net/m0_62386635/article/details/130347385

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_35002.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注