基础知识之KVC原理

在开发中,我们可以通过使用 KVC 的方式来对某个对象的属性进行赋值/取值操作。

经常会用到以下 API:

// 设置值
- (void)setValue:(nullable id)value forKey:(NSString *)key;

- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;

// 获取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;

- (nullable id)valueForKey:(NSString *)key;
1、赋值操作

KVC的调用原理:
如果我们给某个类定义一个属性,那么编译器会自动生成getter和setter方法,如果通过KVC给该属性进行赋值操作,默认会调用setter方法进行赋值,但是这不能完全搞清楚KVC是如何工作的。
现在我们定义一个Person类,但是我们并不给Person定义任何的属性,接下来创建person对象,通过KVC的方式给person的age属性进行赋值操作。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        Person *person = [[Person alloc] init];
        
        [person setValue:@(40) forKey:@"age"];
    }
    return 0;
}

接下来是执行顺序,去Person类中查找有没有- (void)setAge:方法,如果有那么就进行赋值操作;如果没有再去查找有没有- (void)_setAge: 方法,如果有就进行赋值的操作,如果以上2个方法都没找到,那么就会调用- (Bool)accessInstanceVariablesDirectly 方法,该方法是询问是否可以直接访问成员变量,返回NO就直接抛出异常未定的key,返回YES(如果不实现该方法默认返回就是YES),那么就直接去成员变量中按顺序查找以下成员变量:_age_isAgeageisAge。如果找到4个成员变量中的1位,那么就进行赋值,否则抛出异常未定义的key。

2、取值操作

KVC 的取值操作也会按照一定的顺序进行操作的。
在取值的过程中,按照-(int)getAge-(int)age-(int)isAge-(int)_age顺序进行,看有没有实现这4个方法中的其中1个,如果有那么调用,如果没有实现上面的4个方法,继续查看 + (BOOL)accessInstanceVariablesDirectly 方法的返回值是否为 YES,如果为NO,直接抛出异常,如果为YES,那么就去按顺序查找Person的成员变量是不是_age,_isAgeageisAge中的一个,如果有4个成员变量中的1个,那么就取他们的值。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容