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

KVC(三)取值操作的实现

作者: PerryMorning | 来源:发表于2019-11-14 23:17 被阅读0次

前两篇文章主要讲解了KVC的基本使用和赋值操作的实现,今天我们来看一下 - (nullable id)valueForKey:(NSString *)key;是如何通过key进行取值的。

其步骤大致如下:

   1、首先会在接收者的方法列表中,依照 getKey()、key()、isKey()、_key()的顺序,去寻找方法的实现,找到其中一个的话,将其值返回给key对应的属性。

    2、假如第一步查找失败,会在方法列表中查找

           a: -countOf<Key>:(id)key 、

           b: -indexIn<Key>OfObject:()    

           c: -objectIn<Key>AtIndex:(NSInteger)index、

           d: -<key>AtIndexes:(NSInteger)index。

如果找到方法a和b,并且c 和 d至少一个方法,会返回一个NSKeyValueOrderedSet类型的对象A。

当调用集合对象A的count()/objectAtIndex/indexOfObject 等集合方法时,就会调用我们方法列表中实现的对应方法,并将其值返回。

    3、假如第二步没有找到对应的方法,只是找到了方法a和c/d中的至少一个方法,会返回一个NSKeyValueArray类型的对象。并执行对应的集合对象操作,类似于第二步。

    4、加入第三步查找失败,会继续查找以下三个方法:

         a: -countOf<Key>:(id)key;

         b:-enumeratorOf<Key>;

         c:-memberOf<Key>:

    如果三个方法全都存在,会返回一个NSKeyValueSet类型的集合对象,当调用集合的方法时,会调用以上三个方法的实现。

    5、当第四步执行失败,就会访问 +accessInstanceVariablesDirectly(),  当该方法返回YES时,会从对象的成员方法列表中以 _<key>, _is<Key>, <key>, or is<Key>的顺序进行查找匹配,如果找到则返回对应的值。

    6、如果第五步查找失败,会调用 -valueForUndefinedKey(),方法,该方法默认会抛出NSUndefinedKeyException异常,导致程序崩溃。我们可以通过重写此方法,避免程序崩溃。

以上6步就是通过KVC取值的全部过程。

下面我们通过代码来验证。

首先验证步骤一:以height属性为例,在Person类中实现getHeight(),height(),isHeight()和_height()方法。

当我们依次将方法注释后,得到的结果为:111、222、333、444。证明按顺序取值,找到对应方法后,即返回给valueForKey()。

步骤二:假如没有实现以上四个方法,我们以numbers属性为例,声明并实现以下四个方法:

调用valueForKey方法,得到NSKeyValueOrderedSet类型实例,与步骤二结果吻合:

假如我们没有实现numbersAtIndexes:() 或者 objectInNumbersAtIndex()方法,同样的调用,结果也是一样的。

步骤三:假如只实现了-(NSUInteger)countOfNumbers;,同时实现了-(id)objectInNumbersAtIndex:(NSUInteger)index;和- (id)numbersAtIndexes:(NSInteger)index;中的至少一个,再次调用会得到如下结果:

步骤四:假如在接收者中只有以下三个方法实现:

同样的调用会得到类NSKeyValueSet的实例,与步骤4推论吻合。

步骤五:仍旧以numbers为例,在Person类中声明四个成员变量,并对其赋值:

可以依次将_key,_isKey,key,isKey方法注释,查看结果进行验证。

注意+ (BOOL)accessInstanceVariablesDirectly()默认返回值为YES,如果我们重写其方法将其返回NO时,会触发-valueForUndefinedKey()方法。

步骤六:如果+ (BOOL)accessInstanceVariablesDirectly()依旧返回YES,但是并没有找到对应的属性时,依旧会触发-valueForUndefinedKey()方法。

以上就是valueForKey:(NSString*)key 的全部调用过程。中间省去了一些调试变化的过程,各位朋友可以调试各种情况试一下,相信会有新的发现。

虽然按照文档,将整个调用过程用代码翻译了一遍,但是在这里,笔者仍有一个疑问,在通过成员变量取值之前,为什么会先去尝试判断集合属性,这样的设计,是为了什么?有知晓答案的朋友吗,希望能够一起探讨。

相关文章

  • KVC(三)取值操作的实现

    前两篇文章主要讲解了KVC的基本使用和赋值操作的实现,今天我们来看一下是如何通过key进行取值的。 其步骤大致如下...

  • KVC本质

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

  • iOS Objective-C KVC 的常见用法

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

  • KVC详解

    KVC 目录结构KVC定义KVC取值和设置KVC使用keyPathKVC处理字典KVC作用 参考:iOS KVC和...

  • KVO和KVC的使用及原理解析

    一 KVO基本使用 二 KVO本质原理讲解及代码验证 三 KVC基本使用 四 KVC设值原理 五 KVC取值原理 ...

  • iOS KVC (十)模型转换

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

  • iOS KVC (四)keyPath的深度解析

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

  • iOS KVC (五)KVC几种典型的异常处理

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

  • iOS KVC (八) KVC几种常见应用

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

  • iOS KVC(一)基本了解

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

网友评论

    本文标题:KVC(三)取值操作的实现

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