前言
最近在学习 Objc Runtime 相关知识时,思考了一下 Sunnyxx 提出的 “入院考试”,下文主要对 isKindOfClass、isMemberOfClass 的知识点进行整理。
正文
- isKind/MemebrOfClass
我们先来看一下”入院考试”的题目,毕竟要先有需求,才能解决需求
|
|
也许部分开发者看到这已经准备关闭这篇博客,”不就是调用一下,然后输出真假嘛,有什么难的呢?”
稍安勿躁,稍安勿躁~相信大家都知道这两个方法一般情况下的调用情况
- isKindOfClass:判断实例类是否属于传入类的同种类(即当前传入类或当前传入的类的父类或父父类…)
- isMemberOfClass:判断实例类是否等于传入类
因此,一般情况下,这两个方法会像这样执行
|
|
Method Implementation
这两个方法内部是怎么实现的呢?代码之下无秘密,我们来看一下代码:
|
|
+ isKind/MemebrOfClass
接下来我们看看”入院考试”中,消息的发送者,它并不是一个对象,而是一个类。这会发生什么情况呢?我们先来看看”入院考试”的执行结果
|
|
相信如果理解了上述源码的朋友看到这,应该理解了为什么结果会是这样
至于还没有理解的朋友,不用心急,我们下面继续分析
在分析之前,我们首先来看一张关于 isa 指针的传世之图(很抱歉,没找到原图的出处链接)
这里需要注意的是,每个实例会有一个 isa 指针指向它的类,每个类也有一个 isa 指针指向类的类(即元类)。根元类的 isa 指针指向自己,superclass 指针则指向 NSObject(Root Class)
接着,让我们来继续通过注释分析一下
|
|
从上述内容我们可以得到以下规律:
- 对于 [A isKindOfClass:[B class]],只要 A 属于 B 的继承链,则为真
- 对于 [(id)[A class] isKindOfClass:[B class]],仅当 B == NSObject 时为真,A 不影响结果
- 对于 [A isMemberOfClass:[B class]],只要 A == B,即A 与 B 为同一类,则为真
- 对于 [(id)[A class] isMemberOfClass:[B class]],无论 A 与 B 是否相等,必为假
总结:
本文分析了 isKindOfClass 与 isMemberOfClass 的不同点。需要注意的是,对于 object_getClass(obj) 这一方法:若 obj 为类,最终获得的为元类类型 (metaClass);若 obj 为实例,则获得类类型 (class)
本文代码下载
- 示例代码
- 运行环境:Xcode 8.2.1 (8C1002)
- Last Edited:2017.3.11
- Author:@Seahub
- Please contact me if you want to share this Article, 3Q~