前兩天看到一個面試題突然挺感興趣的,然后發(fā)現(xiàn)自己并不能立馬分析出底層原理實現(xiàn),這里抓緊看了一下runtime源碼并按照自己的理解分析了一波,然后得出答案。
1.面試題
BOOL result1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL result2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL result3 = [[Person class] isKindOfClass:[Person class]];
BOOL result4 = [[Person class] isMemberOfClass:[Person class]];
BOOL result5 = [[Person class] isKindOfClass:[NSObject class]];
2.初步分析
我們了解到isKindOfClass是通常是用來判斷A對象是否為B類的實例或其子類的實例對象,官方說明如下:
Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class.
而isMemberOfClass常用來判斷A對象是否為B類的實例對象。
Returns a Boolean value that indicates whether the receiver is an instance of a given class.
既然是判斷實例,那么這里的A應(yīng)該是實例對象才對,而題中A都是Class類。
所以初步得出結(jié)論是:0,0,0,0,1。
3.進一步分析
透過runtime源碼分析到,其實類對象也可以使用這兩個方法的,其中的奧妙如下:
+ (Class)class {
return self;
}
- (Class)class {
return object_getClass(self);
}
+ (Class)superclass {
return self->superclass;
}
- (Class)superclass {
return [self class]->superclass;
}
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
從runtime源碼中我們可以看到類對象和實例對象分別有對應(yīng)的+ (BOOL)isKindOfClass:(Class)cls和- (BOOL)isKindOfClass:(Class)cls方法。所以,并不是我們一開始猜想的那樣。
3.1 + (BOOL)isKindOfClass:(Class)cls分析
當(dāng)調(diào)用對象為類對象的時候,我們可以發(fā)現(xiàn)其底層是一個循環(huán)遍歷判斷。
我們了解到,當(dāng)A對象為NSObject對象時,其isa指針指向的是NSObject元類(Meta),所以第一次循環(huán)元類和類對象肯定是不相等的。接下來第二次循環(huán)是
元類對象的superclass指向的是NSObject本身,所以第二次循環(huán)是返回True的。關(guān)于isa和superclass之間的指向關(guān)系我們可以通過下面這張圖一覽無遺:

3.2 + (BOOL)isMemberOfClass:(Class)cls分析
通過上面這張圖我們可以清晰看到,類方法中只是簡單的做了一個isa指針和class之間的比較。所以,無論是NSObject的isa還是繼承自NSObject的子類的isa都是指向A對象的元類,元類是類本身肯定是不一樣的。
4.再來逐個分析
//問題1: 在3.1中已經(jīng)說明,有兩次循環(huán),第二次會相等
BOOL result1 = [[NSObject class] isKindOfClass:[NSObject class]];
//問題2:類方法是直接拿A對象的isa比較,元類和類不同,所以不相等
BOOL result2 = [[NSObject class] isMemberOfClass:[NSObject class]];
//問題3:逐次循環(huán)分析
//第一次:Person->isa = Person Meta != Person
//第二次:Person Meta -> superclass = NSObject Meta != Person
//第三次:我們看到左邊A對象的superclass會一直沿著關(guān)系圖往上走,一直到nil都不會相等
BOOL result3 = [[Person class] isKindOfClass:[Person class]];
//和問題2相同也不會相等
BOOL result4 = [[Person class] isMemberOfClass:[Person class]];
所以綜合上述,正確的答案應(yīng)該是:1,0,0,0,1。
感謝各位大佬們,歡迎點贊。