美文网首页iOS 底层原理探究
KVC(二)赋值操作的实现

KVC(二)赋值操作的实现

作者: PerryMorning | 来源:发表于2019-11-13 22:22 被阅读0次

上篇文章留了个彩蛋,我们只是声明了成员变量height 和 weight,但是我们通过 setValue: forKey成功对height 和 weight 进行了赋值操作,这背后究竟发生了什么,我们一起来看一下。

首先看官方API,- (void)setValue:(nullableid)valueforKey:(NSString*)key;

通过一个可以标识属性的标识符,给属性赋值,建立起键值一对一的关系,如果key之前有对应的值,则将其解约。

继续看文档,我们发现其默认的实现步骤是先去找 -set<Key>:方法,如果找到,会去检查参数是否为nil,如果为nil,会调用setNilValueForKey方法,默认的实现方式是抛出NSInvalidArgumentException异常,当然我们可以在类中重写此方法,来避免崩溃。

2.如果没有找到-set<Key>:方法,其实会退而求其次,寻找-_set<Key>:方法,如果有则调用-_set<Key>:进行赋值操作。

3.假如-set<Key>: 和 -_set<Key>:都没有找到的话,继续调用+accessInstanceVariablesDirectly,询问是否允许访问成员变量,这个方法系统默认返回YES,也就是可以访问成员变量。

假如我们重写了+accessInstanceVariablesDirectly方法,并返回NO,不允许访问成员变量时,系统会调用-setValue:forUndefinedKey:方法,此方法的默认实现会抛出NSUndefinedKeyException异常,当然我们可以在实现中重写此方法,来避免崩溃。

4.在得到了访问成员变量权限后,会按照_<key>, _is<Key>, <key>, or is<Key>的顺序查看是否有对应的成员变量,如果有则进行赋值。加入最后都没有找到,依旧调用-setValue:forUndefinedKey:方法。

以上就是 - (void)setValue:(nullableid)valueforKey:(NSString*)key 的调用过程,下面 我们通过代码来验证一下,由于系统会自动帮属性创建对应的set、get方法,我们依旧使用成员变量_weight来研究:

设置set方法:

进行调用:

得到如下结果:

由于我们分别实现了setHeight 和 _setHeight方法,在打印结果中,我们看到的是-setHeight方法被调用;对weight成员变量,我们只是实现了 _setWeight方法,因为没有找到setWeight方法,调用_setWeight()方法,和我们上面的分析结果吻合。

(二)当我们为 height 赋值 nil时,如果不做其他操作,系统会抛出异常,为了避免崩溃,只需要在PMPerson中重写-(void)setNilValueForKey:(NSString *)key,如图:

此时再向height传递nil值,就会在控制台看到 “value is not Nil”的打印结果。

(三)加入我们不是想setKey和_setKey方法,同时将+(BOOL)accessInstanceVariablesDirectly返回值设置为nil,如图:

此时再去调用赋值操作,系统则会抛出NSUnknownKeyException异常。只需要重写- (void)setValue:(id)value forUndefinedKey:(NSString *)key即可,如图:

(四)假如允许访问成员变量,就可以解开我们开篇时提到的问题了,为什么通过height和_height都可以进行赋值成功。

我们以weight为例,赋值语句如下:

按照上面的分析,此时只要成员变量中包含 __weight/_is_weight/_weight/is_weight,就可以赋值成功。我们的测试用例如下:

看到这里,我们对- (void)setValue:(nullableid)valueforKey:(NSString*)key;的整个调用过程应该很熟悉了,如果觉得文字太绕了的话,可以看一下下面这幅图:

杰哥的图

再次感谢杰哥的精美制图。

相关文章

  • KVC(二)赋值操作的实现

    上篇文章留了个彩蛋,我们只是声明了成员变量height 和 weight,但是我们通过 setValue: for...

  • KVC本质

    1.赋值操作 2.取值操作 3.用赋值KVC操作是否会触发KVO

  • 第二十三篇:KVC和KVO实现的原理

    KVC被用来进行赋值操作,下面是KVC的官方文档介绍: 下面这些代码是KVC进行赋值时候,其会找set方法,然后进...

  • KVC

    一、KVC KVC就是key-Value-coding,即键值编码,通常情况给某一个对象进行赋值。但是通常赋值操作...

  • Swift4.0 之KVC赋值模型数据

    嗯,没错 KVC 赋值操作 之前好好的swift3.0 赋值操作 所有的key都在swift4.0 变得找不到,...

  • KVC、KVO小结和应用

    KVC 综述 通常,我们使用“.语法”去给对象赋值,而KVC是使用字符串描述对象属性或属性路径从而实现赋值。NSO...

  • Swift从入门到精通-4

    一、KVC 1、在init中调用setValuesForKeysWithDictionary实现给属性赋值 2、调...

  • iOS Objective-C KVC 的常见用法

    iOS Objective-C KVC 的常见用法 前言 在我们的开发中经常会用到kvc给属性赋值或者取值操作,但...

  • KVC 解析

    KVC解析(一) —— 基本了解KVC解析(二) —— 不可不知的赋值深层次原理KVC解析(三) —— 不可不知的...

  • iOS KVC (十)模型转换

    iOS KVC(一)基本了解iOS KVC (二) 不可不知的赋值深层次原理iOS KVC (三)不可不知的取值...

网友评论

    本文标题:KVC(二)赋值操作的实现

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