前两天碰到一面试题:
在这之前,我们先了解一下相关的定义:
Class
在objc.h中Class是这么定义的:
objc_class又是啥呢?在runtime.h中能看见:
|
|
MetaClass
上面能看到Class中有个isa参数,它是指向Class的元类(MetaClass)的指针。
注意到isa也是一个Class的结构体,也就是说MetaClass其本质也是一个Class。
我们可以把Meta Class理解为 一个Class对象的Class。简单的说:
- 当我们发送一个消息给一个NSObject对象时,这条消息会在对象的类的方法列表里查找
- 当我们发送一个消息给一个类时,这条消息会在类的Meta Class的方法列表里查找
之后就有了下面的这张图:

能看到:
- 每个
Class都有一个isa指针指向一个唯一的MetaClass - 每一个
MetaClass的isa指针都指向最上层的MetaClass(图中的NSObject的MetaClass) - 最上层的
MetaClass的isa指针指向自己,形成一个回路 - 每一个
MetaClass的super class指针指向它原本Class的Super Class的MetaClass。 - 最上层的
MetaClass的Super Class指向NSObjectClass本身 - 最上层的
NSObjectClass的super class指向nil
接下来我们看看objc源码中(源码可到这里下载),在文件Object.mm内,上面相关方法的定义:
|
|
|
|
|
|
那么,BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];就可以这样对应起来理解了:
[NSObject class]拿到的是self,类方法的return self,即上图紫色的NSObject(Class)。
根据上面- (BOOL)isKindOf:aClass的实现,for循环首先拿到的cls = isa,也就是cls为NSObject(Class)的MetaClass。显然这时候cls == (Class)aClass不成立。
随后,cls = cls->superclass,即cls变成了NSObject(Class)的MetaClass的superclass,根据图示可以,superclass指向的是NSObject(Class),至此cls == (Class)aClass成立,返回YES。
同样的道理,分析BOOL res3 = [[Sark class] isKindOfClass:[Sark class]];:
[Sark class]拿到的是Sark(Class),而- (BOOL)isKindOf:aClass中cls拿到的值依次是Sark Meta Class->NSObject Meta Class->NSObject Class -> nil,没有相等的,return NO。
剩下两个,根据- (BOOL)isMemberOf:aClass的实现,很容易得出结论会return NO。