下面代碼的運行結果是?函數
@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 。