• 【iOS】—— KVC


    KVC

    KVC概念

    KVC全称是Key-Value-Coding,键值编码,可以通过一个key来访问某个属性。

    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来设值
    
    
    

    在这里要注意的是前两种方法是KVC的设值,后两种方法是KVC的取值。

    其他方法
    // 默认返回YES,表示如果没有找到Set方法的话,会按照_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;
    
    
    

    首先我们来看设值

    设值

    最简单的是用key方法直接设值:

    Person* person = [[Person alloc]init];
     [person setValue:@namevalue forKey:@"name"];
    
    
    

    还可以使用keyPath方法进行多重设值

    Person* person = [[Person alloc]init];
    [person setValue:@1 forKeyPath:@"dog.age"];
    
    id age = [person valueForKeyPath:@"dog.age"];
    NSLog(@"%@", age);
    

    Dog类和Person类是两个继承NSObject的类,先在Person类里面设置Dog类型的属性,在Dog类里设置int类型的age属性,即可完成设值过程。

    取值

    在取值过程中,优先级是最重要的一点,一定要搞清楚KVC取值的优先级,我们可以先来看下图:

    请添加图片描述
    请添加图片描述

    第一优先级

    在这个过程中,第一优先级是getter方法,也就是说在取值的时候,先判断有没有getter方法,如果有的话直接取值成功,不需要后面的步骤了。

    - (NSString*)name {
        return @"666";
    }
    - (NSString*)getName {
        return @"get666";
    }
    - (NSString*)isName {
        return @"is666";
    }
    

    我们在Person的m文件中把三个getter方法全写上,此时打印:

    Person* person = [[Person alloc]init];
        NSString* name = [person valueForKey:@"name"];
        NSLog(@"%@", name);
    

    在这里插入图片描述

    我们发现在所有getter方法里面,优先级最高的是getName方法,然后我们把这个方法注释掉,经过实验得出结论:

    在三个getter方法中,优先级排序:
    getKey > key > isKey

    第二优先级

    我们发现上图中在第二优先级前面有一个方法,这个方法是什么呢,我们来看看:
    在这里插入图片描述

    + (BOOL)accessInstanceVariablesDirectly
    

    这个方法是BOOL类型,用来判断是否需要查找第二优先级,默认情况下为Yes,如果返回值改为No,就跳过查找第二优先级。

    此时我们对成员变量通过重写init方法进行赋值:

    - (instancetype)init {
        if (self = [super init]) {
            //成员变量
            _name = @"_name";
            _isName = @"_isName";
            name = @"name";
            isName = @"isName";
        }
        return self;
    }
    

    在进行第二级优先级测试的时候,先把第一优先级的方法注释起来,然后运行程序:
    请添加图片描述

    同样用刚才相同的方法进行测试,发现第二级方法的优先级:

    _key > _iskey > key > iskey

    那么如果两种情况都没有呢?

    我们将代码都注释掉来试试:
    在这里插入图片描述

    这时候程序编译没问题,运行时就会报经典的Undefine问题了。

    KVC问题其实是一个比较抽象的问题,如果文章难以理解的话,这里推荐一个视频博主,关于此节内容讲解十分细致:
    KVC视频链接

  • 相关阅读:
    网格bfs,LeetCode 2684. 矩阵中移动的最大次数
    LeetCode(力扣)63. 不同路径 IIPython
    Java访问修饰符学习资料
    团队开发(git的使用及注意事项)
    JVM 方法内联
    【计算机网络】HTTPS的基础知识
    计算机网络刷题:计算机网络概述
    热乎的腾讯 C++ 后台开发面试笔记
    新手小白学JAVA Lambda表达式
    iis站点https绑定
  • 原文地址:https://blog.csdn.net/m0_62386635/article/details/126959140