題一
@interface LGPerson : NSObject
- (void)sayHello;
+ (void)sayHappy;
@end
void lgInstanceMethod_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getInstanceMethod(pClass, @selector(sayHello));
Method method2 = class_getInstanceMethod(metaClass, @selector(sayHello));
Method method3 = class_getInstanceMethod(pClass, @selector(sayHappy));
Method method4 = class_getInstanceMethod(metaClass, @selector(sayHappy));
LGLog(@"%s - %p-%p-%p-%p",__func__,method1,method2,method3,method4);
}
void lgClassMethod_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getClassMethod(pClass, @selector(sayHello));
Method method2 = class_getClassMethod(metaClass, @selector(sayHello));
Method method3 = class_getClassMethod(pClass, @selector(sayHappy));
Method method4 = class_getClassMethod(metaClass, @selector(sayHappy));
LGLog(@"%s-%p-%p-%p-%p",__func__,method1,method2,method3,method4);
}
LGPerson *person = [LGPerson alloc];
Class pClass = object_getClass(person);
lgInstanceMethod_classToMetaclass(pClass);
lgClassMethod_classToMetaclass(pClass);
打印結(jié)果:
lgInstanceMethod_classToMetaclass - 0x1000031a8-0x0-0x0-0x100003140
lgClassMethod_classToMetaclass-0x0-0x0-0x100003140-0x100003140
首先傳入?yún)?shù)pClass,是LGPerson類。
lgInstanceMethod_classToMetaclass方法中,pClass為LGPerson類,metaClass為LGPerson元類。
class_getInstanceMethod從傳入的類或者類的父類中查找指定的實(shí)例方法。
- class_getInstanceMethod(pClass, @selector(sayHello))中,pClass為LGPerson類,查找sayHello實(shí)例方法,在LGPerson類找到了sayHello方法。
- class_getInstanceMethod(metaClass, @selector(sayHello))中,metaClass為LGPerson元類,根據(jù)sayHello查找實(shí)例方法,查找鏈路LGPerson元類->NSobject根元類->NSobject類->nil,sayHello在LGPerson類中,所以不能找到。
- class_getInstanceMethod(pClass, @selector(sayHappy))中,pClass為LGPerson類,根據(jù)sayHello查找實(shí)例方法,查找鏈路LGPerson類->NSobject類->nil,sayHappy在LGPerson元類中,所以不能找到。
- class_getInstanceMethod(metaClass, @selector(sayHappy))中,metaClass為LGPerson元類,根菌sayHappy查找實(shí)例方法,從LGPerson元類開始根據(jù)sayHappy查找實(shí)例方法,sayHappy在LGPerson元類中,所以找到了。
lgClassMethod_classToMetaclass方法中,pClass為LGPerson類,metaClass為LGPerson元類。
class_getClassMethod方法會先查找到對應(yīng)的元類,再查找方法。
- class_getClassMethod(pClass, @selector(sayHello))中,pClass為LGPerson類,找到LGPerson元類,無法查找到sayHello方法。
- class_getClassMethod(metaClass, @selector(sayHello))中,metaClass本身為LGPerson元類
,無法查找到sayHello方法。 - class_getClassMethod(pClass, @selector(sayHappy)),pClass為LGPerson類,找到LGPerson元類,查找到sayHappy方法。
- class_getClassMethod(metaClass, @selector(sayHappy)),metaClass為LGPerson元類
查找到sayHappy方法。
題二
LGPerson繼承自NSObject
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);
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);
估計很多人都能答,但今天我們研究的是解答這道題的過程中所涉及的一些知識。
class、isKindOfClass、isMemberOfClass
首先我們來看class類方法,經(jīng)過斷點(diǎn)調(diào)試發(fā)現(xiàn)其會進(jìn)入:
Class
objc_opt_class(id obj)
{
#if __OBJC2__
if (slowpath(!obj)) return nil;
Class cls = obj->getIsa();
if (fastpath(!cls->hasCustomCore())) {
return cls->isMetaClass() ? obj : cls;
}
#endif
return ((Class(*)(id, SEL))objc_msgSend)(obj, @selector(class));
}
我們知道實(shí)例的isa是指向類的,類的isa指向元類。根據(jù)源碼理解,如果obj是類,那么就返回自己,如果是實(shí)例就返回其對應(yīng)的類。
isKindOfClass方法,我們?nèi)タ雌湓创a實(shí)現(xiàn):
+ (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;
}
isKindOfClass類方法房和實(shí)例方法,區(qū)別在于類方法是調(diào)用ISA而實(shí)例方法是調(diào)用class方法,otherClass是做比較的Class。tcls從cls開始,順著其類的繼承鏈查找,如果找到和otherClass相同則返回YES,最終找不到則返回NO.
isMemberOfClass方法,其源碼實(shí)現(xiàn)為:
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
類方法調(diào)用class方法后返回值判斷是否和cls相同,實(shí)例方法調(diào)用ISA方法后返回值判斷是否和cls相同。
題目分析
相關(guān)概念有了了解后我們開始來對題目來一一進(jìn)行分析:
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
[NSObject class]對應(yīng)的就是NSObject類。
調(diào)用isKindOfClass后,前面的的NSObject類調(diào)用getIsa()后就是NSObject根元類,otherClass即是NSObject類。
進(jìn)入for循環(huán)判斷
第一步:NSObject根元類和NSObject類不相等,NSObject根元類調(diào)用superclass
第二步:NSObject根元類的superclass為NSObject類(這點(diǎn)不明白可以去了解下isa、super走位圖),兩者相等,返回YES.
re1為1.
BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
[NSObject class]對應(yīng)的就是NSObject類,調(diào)用isMemberOfClass后,
前面的NSObject類會調(diào)用ISA(),變成了NSObject根元類,和后面的NSObject類比較不相等。re2結(jié)果為0。
BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];
[LGPerson class]對應(yīng)的就是LGPerson類,調(diào)用isKindOfClass后,前面的LGPerson類會調(diào)用ISA(),變成了LGPerson元類.
進(jìn)入for循環(huán)判斷
第一步:LGPerson元類和LGPerson類比較不相等,LGPerson元類調(diào)用superclass.
第二步:LGPerson元類的superclass為NSObject根元類,NSObject根元類和LGPerson類比較還是不相等。繼續(xù)superclass。
第三步:NSObject根元類繼續(xù)superclass得到NSObject類,和LGPerson類比較不相等。繼續(xù)superclass
第四步:NSObject類superclass為nil,和LGPerson類比較不相等。并且因?yàn)閚il退出循環(huán),最終返回NO.
re3為0;
BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];
[LGPerson class]對應(yīng)的就是LGPerson類,調(diào)用isMemberOfClass后,前面的LGPerson類會調(diào)用ISA(),變成了LGPerson元類,和后面的NSObject類比較不相等。
re4結(jié)果為0。
BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];
[NSObject alloc]得到的是一個NSObject實(shí)例,[NSObject class]得到NSObject類。
調(diào)用isKindOfClass后,前面的的NSObject實(shí)例調(diào)用class方法后就是NSObject類,跟后面的NSObject類比較相等,返回YES.
re5為1.
BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];
[NSObject alloc]得到的是一個NSObject實(shí)例,[NSObject class]得到NSObject類。
調(diào)用isMemberOfClass后,前面的的NSObject實(shí)例調(diào)用class方法后就是NSObject類,跟后面的NSObject類比較相等,返回YES.
re6為1.
BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];
[LGPerson alloc]得到的是一個LGPerson實(shí)例,[LGPerson class]得到LGPerson類。
調(diào)用isKindOfClass后,前面的的LGPerson實(shí)例調(diào)用class方法后就是LGPerson類,跟后面的LGPerson類比較相等,返回YES.
re7為1.
BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];
[LGPerson alloc]得到的是一個LGPerson實(shí)例,[LGPerson class]得到LGPerson類。
調(diào)用isMemberOfClass后,前面的的LGPerson實(shí)例調(diào)用class方法后就是LGPerson類,跟后面的LGPerson類比較相等,返回YES.
re8為1.
最終結(jié)果為:
re1 :1
re2 :0
re3 :0
re4 :0
re5 :1
re6 :1
re7 :1
re8 :1