首先抛出最常见的关于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了吧