美文网首页
iOS中的KVC

iOS中的KVC

作者: 炒河粉儿 | 来源:发表于2019-08-03 16:25 被阅读0次

    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。

    相关文章

      网友评论

          本文标题:iOS中的KVC

          本文链接:https://www.haomeiwen.com/subject/hbgjdctx.html