1. 下面的代碼輸出什么內(nèi)容奠货?
@interface LGPerson : NSObject
- (void)sayHello;
+ (void)sayHappy;
@end
@implementation LGPerson
- (void)sayHello{
NSLog(@"LGPerson say : Hello!!!");
}
+ (void)sayHappy{
NSLog(@"LGPerson say : Happy!!!");
}
@end
1.1
void lgInstanceMethod_classToMetaclass(Class pClass){
// 其中pClass中sayHello定義為實例方法,sayHappy定義為類方法
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);
}
解答:根據(jù)之前的學(xué)習(xí)我們知道其實并不存在什么類方法棚贾,類方法就是元類的實例方法
琳骡,所以答案是:0xXXXXXXX-0x0-0x0-0xXXXXXXXX
。
1.2
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);
}
解答:此題的難點在于class_getClassMethod
的背后的實現(xiàn)原理
倾哺。有下面的實現(xiàn)代碼可知class_getClassMethod
其實就是找了傳入的cls的元類
再調(diào)用class_getInstanceMethod函數(shù)
,這里面還有一個坑點在于getMeta函數(shù)
的實現(xiàn)刽脖,在調(diào)用getMeta函數(shù)
時會先判斷當(dāng)前傳入的類是否是元類
悼粮,如果是直接返回當(dāng)前類,如果不是則通過isa返回元類
曾棕。所以不論怎樣都會返回正確的元類
。所以本題的答案是:0x0-0x0-0xXXXXXXXX-0xXXXXXXX
菜循。
Method class_getClassMethod(Class cls, SEL sel)
{
if (!cls || !sel) return nil;
return class_getInstanceMethod(cls->getMeta(), sel);
}
Class getMeta() {
if (isMetaClassMaybeUnrealized()) return (Class)this;
else return this->ISA();
}
1.3
void lgIMP_classToMetaclass(Class pClass) {
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
IMP imp1 = class_getMethodImplementation(pClass, @selector(sayHello));
IMP imp2 = class_getMethodImplementation(metaClass, @selector(sayHello));
IMP imp3 = class_getMethodImplementation(pClass, @selector(sayHappy));
IMP imp4 = class_getMethodImplementation(metaClass, @selector(sayHappy));
NSLog(@"%p-%p-%p-%p",imp1,imp2,imp3,imp4);
NSLog(@"%s",__func__);
}
此題的難點還是在于函數(shù)的實現(xiàn)翘地,imp1和imp4毫無疑問肯定可以找到對應(yīng)的實現(xiàn),但是當(dāng)當(dāng)前類沒有對應(yīng)實現(xiàn)的時候會返回默認(rèn)的消息轉(zhuǎn)發(fā)實現(xiàn)_objc_msgForward
__attribute__((flatten))
IMP class_getMethodImplementation(Class cls, SEL sel)
{
IMP imp;
if (!cls || !sel) return nil;
lockdebug_assert_no_locks_locked_except({ &loadMethodLock });
imp = lookUpImpOrNilTryCache(nil, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER);
// Translate forwarding function to C-callable external version
if (!imp) {
return _objc_msgForward;
}
return imp;
}
2. iskindOfClass & isMemberOfClass 的理解
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
- iskindOfClass & isMemberOfClass 類方法調(diào)用
//-----使用 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
的類方法實現(xiàn)
會以當(dāng)前類的元類
為初始值和傳入的類
進(jìn)行比較,如果相同則返回YES
衙耕,如果不相等則不停的取當(dāng)前類的元類的superclass
與傳入的類進(jìn)行比較昧穿,如果相等則返回YES
,如果一直到nil都沒有相等則返回NO
橙喘。
isMemberOfClass
的類方法實現(xiàn)
則是判斷當(dāng)前類的元類是否等于傳入類
时鸵,如果相等返回YES,如果不相等返回NO厅瞎。
當(dāng)傳入的類不是元類時饰潜,進(jìn)行類方法的調(diào)用,isKindOfClass只有NSObject才會返回YES和簸,isMemberOfClass則永遠(yuǎn)不會返回YES
彭雾。故本題的答案是1-0-0-0
。
- iskindOfClass & isMemberOfClass 實例方法調(diào)用
//------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);
解答:
isKindOfClass
的實例方法實現(xiàn)
會以當(dāng)前實例的類為初始值和
傳入的類進(jìn)行比較锁保,如果相同則返回YES
薯酝,如果不相等則不停的取當(dāng)前實例的類的superclass
與傳入的類進(jìn)行比較,如果相等則返回YES
爽柒,如果一直到nil都沒有相等則返回NO
吴菠,簡單來說就是判斷當(dāng)前實例是否是傳入類及其所有子類的實例
。
isMemberOfClass
的類方法實現(xiàn)
則是判斷當(dāng)前實例的類是否等于傳入類
浩村,如果相等返回YES做葵,如果不相等返回NO。
故此題的答案是1-1-1-1穴亏。
總結(jié)
isKindOfClass
類方法:元類->父元類->...->根源類->根類
與傳入的類
進(jìn)行比較蜂挪,有一個相等則返回YES,沒有則返回NO嗓化。
實例方法:類->父類->...->根類
與傳入的類
進(jìn)行比較棠涮,有一個相等則返回YES,沒有則返回NO刺覆。isMemberOfClass
類方法:元類
與傳入的類
進(jìn)行比較严肪,相等則返回YES,不相等則返回NO谦屑。
實例方法:類
與傳入的類
進(jìn)行比較驳糯,相等則返回YES,不相等則返回NO氢橙。