KVC的底层分析

705 阅读3分钟

首先抛出最常见的关于kvc的两个面试题:

1.kvc的赋值和取值过程是怎么样的?原理是什么?

2.通过kvc修改属性会触发kvo吗?

这篇文章就是围绕这2个问题来阐述的,相信你看完了一定会对这两个问题有一个深刻的了解.

KVC回顾

KVC(Key-value coding)键值编码,就是指iOS的开发中,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。这样就可以在运行时动态地访问和修改对象的属性。而不是在编译时确定,这也是iOS开发中的黑魔法之一。很多高级的iOS开发技巧都是基于KVC实现的。

下面是KVC最为重要的四个方法:

-(nullable id)valueForKey:(NSString*)key;

-(void)setValue:(nullable id)value forKey:(NSString*)key;

-(nullable id)valueForKeyPath:(NSString*)keyPath;

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

如果你想获得当前类的属性,你就用valueForKey和key,如果你想赋值复杂的比如上面说的cat中的weight,那你必须要用valueForKeyPath和keyPath来获取和操作,这个都是比较简单的,简单回顾一下.接下来进入正题

1.kvc的赋值和取值过程是怎么样的?原理是什么?

我门先用一张图来说明setValue:forKey:的原理(图可能不够清晰哈,没关系,会一步一步证明)

一、首先会去查找setKey:,_setKey方法,找到方法直接赋值,找不到进行下一步;

我们先在GDPerson写出这2个方法,看看是不是执行到里面了(注意:.h方法不写属性,因为属性直接会生成set、get方法),我们直接在.m中写出这2个方法)

从上面的截图很容易看出来,先找setKey,找到直接赋值,找不到就找_setKey,找到直接赋值,找不到就崩溃,直接报NSUnknownKeyException,找不到这个key吧!

二、执行+(BOOL)accessInstanceVariablesDirectly

这个方法是告诉程序到底有没有这个key,默认是yes,就是有这个key,所以我们如果返回no,直接程序就会报错吧!这个比较简单,大家可以直接复制代码验证一下就行,如果返回的是yes就会进入下一步.

+(BOOL)accessInstanceVariablesDirectly{

return NO;

}

三、接着按照_key、_iskey、key、iskey找赋值

我们先写四个成员变量如下:

{

@public

int_age;

int_isage;

int age;

int isage;

}

这里可以看出优先顺序就是_age、_isage、age、isage(大家可以把 int_age;去掉就能试出第二个,依次类推就行)

如果这4个都找不到就会直接报NSUnknownKeyException,找到了就直接赋值

这就是kvc赋值的整个过程,同样的-(void)setValue:(nullable id)value forKey:(NSString*)key;赋值的过程也是类似如此,大家可以试一下,用我上面的方法去尝试,这也就知道这道面试题怎么解答了,上面那张图就是答案,相信大家这么回答,面试官应该是非常满意了!

2.通过kvc修改属性会触发kvo吗?

请看下面的代码,我们先用代码验证结果,再说过程

从上面的截图,很容易看出来,无论是forKey还是forKeyPath都是触发了kvo

从我们上一篇博客我们知道,直接修改成员变量的值是不会触发kvo的(之前是类似person.age=10),但是kvc的修改为什么就行了呢?

这里我可以告诉大家是因为,用kvc赋值的时候,会调用到

从之前kvo的学习我们知道,调用-(void)willChangeValueForKey:(NSString *)key、-(void)didChangeValueForKey:(NSString *)key就会触发kvo,这下就很清楚,为什么说kvc能触发kvo了吧

接下来博客我会介绍iOS类别(Category)的底层知识.

如果觉得我写得对您有所帮助,请关注我,我会持续更新😄