下面代码的运行结果是?函数
@interface Sark : NSObject @end @implementation Sark @end int main(int argc, const char * argv[]) { @autoreleasepool { BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; BOOL res2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; BOOL res3 = [(id)[Sark class] isKindOfClass:[Sark class]]; BOOL res4 = [(id)[Sark class] isMemberOfClass:[Sark class]]; NSLog(@"%d %d %d %d", res1, res2, res3, res4); } return 0; }
运行结果为:设计
2014-11-05 14:45:08.474 Test[9412:721945] 1 0 0 0
id 在 objc.h 中定义以下:指针
/// A pointer to an instance of a class. typedef struct objc_object *id;
就像注释中所说的这样 id 是指向一个 objc_object 结构体的指针。code
id 这个struct的定义自己就带了一个 *, 因此咱们在使用其余NSObject类型的实例时须要在前面加上 *, 而使用 id 时却不用。
对象
objc_object 在 objc.h 中定义以下:get
/// Represents an instance of a class. struct objc_object { Class isa; };
这个时候咱们知道Objective-C中的object在最后会被转换成C的结构体,而在这个struct中有一个 isa 指针,指向它的类别 Class。it
在 objc.h 中定义以下:io
/// An opaque type that represents an Objective-C class. typedef struct objc_class *Class;
咱们能够看到 Class自己指向的也是一个C的struct objc_class
。class
继续看在runtime.h中objc_class
定义以下:object
struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; const char *name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; struct objc_method_list **methodLists OBJC2_UNAVAILABLE; struct objc_cache *cache OBJC2_UNAVAILABLE; struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE;
该结构体中,isa 指向所属Class, super_class指向父类别。
下载objc源代码,在 objc-runtime-new.h 中,咱们发现 objc_class
有以下定义:
struct objc_class : objc_object { // Class ISA; Class superclass; ... ... }
豁然开朗,咱们看到在Objective-C的设计哲学中,一切都是对象。Class在设计中自己也是一个对象。而这个Class对象的对应的类,咱们叫它 Meta Class
。即Class结构体中的 isa 指向的就是它的 Meta Class
。
根据上面的描述,咱们能够把Meta Class
理解为 一个Class对象的Class
。简单的说:
而 Meta Class自己也是一个Class,它跟其余Class同样也有本身的 isa 和 super_class 指针。看下图:
最上层的Meta Class的isa指针指向本身,造成一个回路
可是最上层的Meta Class的 Super Class指向NSObject Class自己
为了更加清楚的知道整个函数调用过程,咱们使用clang -rewrite-objc main.m
重写,可得到以下代码:
BOOL res1 = ((BOOL (*)(id, SEL, Class))(void *)objc_msgSend)((id)((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("class")), sel_registerName("isKindOfClass:"), ((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("class"))); BOOL res2 = ((BOOL (*)(id, SEL, Class))(void *)objc_msgSend)((id)((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("class")), sel_registerName("isMemberOfClass:"), ((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("class"))); BOOL res3 = ((BOOL (*)(id, SEL, Class))(void *)objc_msgSend)((id)((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Sark"), sel_registerName("class")), sel_registerName("isMemberOfClass:"), ((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("class"))); BOOL res4 = ((BOOL (*)(id, SEL, Class))(void *)objc_msgSend)((id)((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Sark"), sel_registerName("class")), sel_registerName("isMemberOfClass:"), ((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("class")));
objc_msgSend
函数,转发消息。(id)((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("class"))
((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("class"))
咱们注意到第一个参数和第三个参数对应重写的是[NSObject class]
,即便用objc_msgSend
向 NSObject Class 发送 @selector(class) 这个消息
打开objc源代码,在 Object.mm 中发现+ (Class)class
实现以下:
+ (Class)class { return self; }
因此即返回Class类的对象自己。看以下输出:
NSLog(@"%p", [NSObject class]); NSLog(@"%p", [NSObject class]); 2014-11-05 18:48:30.939 Test[11682:865988] 0x7fff768d40f0 2014-11-05 18:48:30.940 Test[11682:865988] 0x7fff768d40f0
继续打开objc源代码,在 Object.mm 中,咱们发现 isKindOfClass
的实现以下:
- (BOOL)isKindOf:aClass { Class cls; for (cls = isa; cls; cls = cls->superclass) if (cls == (Class)aClass) return YES; return NO; }
对着上面Meta Class的图和实现,咱们能够看出
因此上述第一个输出结果是 YES 。
咱们在看下 ‘isMemberOfClass’的实现:
- (BOOL)isMemberOf:aClass { return isa == (Class)aClass; }
综上所述,当前的 isa 指向 NSObject 的 Meta Class, 因此和 NSObject Class不相等。
因此上述第二个输出结果为 NO 。
因此后面两个调用的结果都输出为 NO 。