前言:先來張熟悉又陌生的圖:
isa流程圖.png
【面試題一】
iskindOfClass
& isMemberOfClass
的理解下面代碼亏娜,怎么打印焕窝,并分析原因
int main(int argc, const char * argv[]) {
@autoreleasepool {
//-----使用 iskindOfClass & isMemberOfClass 類方法
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; //
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; //
BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]]; //
BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]]; //
NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);
//------iskindOfClass & isMemberOfClass 實例方法
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; //
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; //
BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]]; //
BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]]; //
NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
}
return 0;
}
打印如下:
re1 :1
re2 :0
re3 :0
re4 :0
re5:1
re6:1
re7:1
re8:1
結(jié)果已給,你細品照藻,你細細的品袜啃;接下來汗侵,解釋一波幸缕,有錯,請留言晰韵,不要發(fā)紅包发乔。
源碼分析一波
-isKindOfClass
源碼解析(實例方法 & 類方法)
//--isKindOfClass---類方法、對象方法
//+ isKindOfClass:第一次比較是 獲取類的元類 與 傳入類對比雪猪,再次之后的對比是獲取上次結(jié)果的父類 與 傳入 類進行對比
+ (BOOL)isKindOfClass:(Class)cls {
// 獲取類的元類 vs 傳入類
// 根元類 vs 傳入類
// 根類 vs 傳入類
// 舉例:LGPerson vs 元類 (根元類) (NSObject)
for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
//- `isKindOfClass`:第一次是獲取對象類 與 傳入類對比栏尚,如果不相等,后續(xù)對比是繼續(xù)獲取上次 類的父類 與傳入類進行對比
- (BOOL)isKindOfClass:(Class)cls {
/*
獲取對象的類 vs 傳入的類
父類 vs 傳入的類
根類 vs 傳入的類
nil vs 傳入的類
*/
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
-
isMemberOfClass
源碼解析(實例方法 & 類方法)
//-----類方法
//+ isMemberOfClass : 獲取類的元類只恨,與 傳入類對比
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
//-----實例方法
//- isMemberOfClass : 獲取對象的類译仗,與 傳入類對比
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
"強行解釋一波"是有依據(jù)的,總結(jié)如下:
<article class="_2rhmJa">
-
isKindOfClass
- 類方法:
元類 --> 根元類 --> 根類 --> nil
與傳入類
的對比 - 實例方法:
對象的類 --> 父類 --> 根類 --> nil
與傳入類
的對比
- 類方法:
-
isMemberOfClass
- 類方法:
類的元類
與傳入類
對比 - 實例方法:
對象的父類
與傳入類
對比
- 類方法:
案例代碼執(zhí)行結(jié)果分析
根據(jù)源碼的分析官觅,來分析代碼執(zhí)行的結(jié)果為什么是0
或者1
使用類方法結(jié)果解析
-
re1 :1 纵菌,是
NSObject
與NSObject
的對比,使用+isKindOfClass
- NSObject(傳入類休涤,即
根類
) vs NSObject的元類即根元類
-- 不相等 - NSObject(傳入類咱圆,即
根類
) vs 根元類的父類即根類
-- 相等,返回1
- NSObject(傳入類休涤,即
-
re2 :0 功氨,是
NSObject
與NSObject
的對比序苏,使用+isMemberOfClass
- NSObject
根類
(傳入類) vs NSObject的元類即根元類
-- 不相等
- NSObject
-
re3 :0 ,是
LGPerson
與LGPerson
的對比捷凄,使用+isisKindOfClass
- LGPerson(傳入
類
) vs LGPerson的元類即元類
LGPerson -- 不相等 - LGPerson(傳入
類
) vs 元類LGPerson的父類即根元類
-- 不相等 - LGPerson(傳入
類
) vs 根元類的父類即根類
-- 不相等 - LGPerson(傳入
類
) vs 根類的父類即nil
-- 不相等
- LGPerson(傳入
-
re4 :0 忱详,是
LGPerson
與LGPerson
的對比,使用+isMemberOfClass
- LGPerson(傳入
類
) vs元類
-- 不相等
- LGPerson(傳入
使用實例方法結(jié)果解析
-
re5 :1 跺涤,是
NSObject對象
與NSObject
的對比踱阿,使用-isKindOfClass
- NSObject(傳入類,即根類) vs 對象的類即NSObject根類 -- 相等
-
re6 :1 钦铁,是
NSObject對象
與NSObject
的對比软舌,使用-isMemberOfClass
- NSObject(傳入類,即根類) vs 對象的類即NSObject根類 -- 相等
-
re7 :1 牛曹,是
LGPerson對象
與LGPerson
的對比佛点,使用-isKindOfClass
- LGPerson(傳入類) vs 對象的類即LGPerson -- 相等
-
re8 :1 ,是
LGPerson對象
與LGPerson
的對比,使用-isMemberOfClass
- NSObject(傳入類) vs 對象的類即LGPerson -- 相等