想要深入立即isKindOfClass和isMemberOfClass的區(qū)別,那就離不開下面這個(gè)圖

image.png
isa 走位鏈(兩條)
teacher的isa走位鏈:
teacher(子類對象) --> CJLTeacher (子類)--> CJLTeacher(子元類) --> NSObject(根元類) --> NSObject(跟根元類,即自己)person的isa走位圖:
person(父類對象) --> CJLPerson (父類)--> CJLPerson(父元類) --> NSObject(根元類) --> NSObject(跟根元類,即自己)
superclass走位鏈(兩條)
類的繼承關(guān)系鏈:
CJLTeacher(子類) --> CJLPerson(父類) --> NSObject(根類)--> nil元類的繼承關(guān)系鏈:
CJLTeacher(子元類) --> CJLPerson(父元類) --> NSObject(根元類)--> NSObject(根類)--> nil
示例分享
//LGPerson 繼承自 NSObject
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
BOOL re2 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];
BOOL re3 = [(id)[NSObject class] isMemberOfClass:[NSObject 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);
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];
BOOL re6 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];
BOOL re7 = [(id)[NSObject alloc] isMemberOfClass:[NSObject 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);
輸出
2020-09-20 21:15:13.975631+0800 KCObjc[2274:69804]
re1 :1
re2 :0
re3 :0
re4 :0
2020-09-20 21:15:13.976631+0800 KCObjc[2274:69804]
re5 :1
re6 :1
re7 :1
re8 :1
源碼分析
+ (BOOL)isKindOfClass:(Class)cls
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
// 獲取類的元類 vs 傳入類
// 根元類 vs 傳入類
// 根類 vs 傳入類
if (tcls == cls) return YES;
}
return NO;
}
- 1、 BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
- 傳入的
cls為NSObject(根類),self指向NSObject,進(jìn)入循環(huán)tcls= NSObject meta(根元類),執(zhí)行判斷if (tcls == cls),不相等,進(jìn)入下一個(gè)循環(huán)tcls= NSObject(根類),執(zhí)行判斷if (tcls == cls),相等,return YES
- 2、 BOOL re2 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];
- 傳入的
cls為LGPerson,self指向LGPerson,進(jìn)入循環(huán)tcls= LGPerson meta(元類),執(zhí)行判斷if (tcls == cls),不相等,進(jìn)入下一個(gè)循環(huán)tcls= NSObject meta(根元類),執(zhí)行判斷if (tcls == cls),不相等,進(jìn)入下一個(gè)循環(huán)tcls= NSObject meta(根類),執(zhí)行判斷if (tcls == cls),不相等,進(jìn)入下一個(gè)循環(huán)tcls= nil,結(jié)束循環(huán),
+ (BOOL)isMemberOfClass:(Class)cls
+ (BOOL)isMemberOfClass:(Class)cls {
//獲取類的元類,與 傳入類對比
return self->ISA() == cls;
}
- 3、 BOOL re3 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
- 傳入的
cls為NSObject(根類),self指向NSObject,進(jìn)入循環(huán)tcls= NSObject meta(根元類),執(zhí)行判斷if (tcls == cls),不相等
- 4、 BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];
- 傳入的
cls為LGPerson,self指向LGPerson,進(jìn)入循環(huán)tcls= NSObject meta(元類),執(zhí)行判斷if (tcls == cls),不相等
- (BOOL)isKindOfClass:(Class)cls
- (BOOL)isKindOfClass:(Class)cls {
//獲取對象的類 vs 傳入的類
//父類 vs 傳入的類
//根類 vs 傳入的類
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
- 1、 BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];
- 傳入的
cls為NSObject(根類),self指向NSObject實(shí)例對象,進(jìn)入循環(huán),NSObject實(shí)例對象的isa即NSObject(根類)tcls= NSObject(根類),執(zhí)行判斷if (tcls == cls),相等
- 2、 BOOL re6 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];
- 傳入的
cls為LGPerson,self指向LGPerson實(shí)例對象,進(jìn)入循環(huán),LGPerson實(shí)例對象的isa即LGPersontcls= LGPerson,執(zhí)行判斷if (tcls == cls),相等
- (BOOL)isMemberOfClass:(Class)cls
- (BOOL)isMemberOfClass:(Class)cls {
//獲取對象的類,與 傳入類對比
return [self class] == cls;
}
- 1、 BOOL re7 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];
- 傳入的
cls為NSObject(根類),self指向NSObject實(shí)例對象,進(jìn)入循環(huán),NSObject實(shí)例對象的類即NSObject(根類)tcls= NSObject(根類),執(zhí)行判斷if (tcls == cls),相等
- 2、 BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];
- 傳入的
cls為LGPerson,self指向LGPerson實(shí)例對象,進(jìn)入循環(huán),LGPerson實(shí)例對象的類即LGPersontcls= LGPerson,執(zhí)行判斷if (tcls == cls),相等
總結(jié)
isKindOfClass
- 類方法:
類和元類的繼承鏈對比
元類(isa) --> 根元類(父類) --> 根類(父類) --> nil(父類)- 實(shí)例方法:
對象的類 --> 父類 --> 根類 --> nil與傳入類的對比
isMemberOfClass
- 類方法:
類的元類與傳入類對比- 實(shí)例方法:
對象的父類與傳入類對比