消失的類方法
在類結(jié)構(gòu)中,我們說了如何通過地址偏移查找類相關(guān)信息婚惫。但是,如果我們?cè)?code>Person類中添加一個(gè)類方法,你會(huì)發(fā)現(xiàn)無法在類信息中找到烤黍。
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
- (void)run;
+ (void)find;
@end
@implementation Person
- (void)run {
};
+ (void)find {
};
通過上一章的方法查看methods,無法找到類方法+(void)find
類方法獲取
Runtime
中為我們提供了獲取方法的函數(shù)class_getInstanceMethod
與class_getClassMethod
赵誓。
我們先來看看Runtime是怎么拿到類方法的。
Method class_getClassMethod(Class cls, SEL sel)
{
if (!cls || !sel) return nil;
return class_getInstanceMethod(cls->getMeta(), sel);
}
Class getMeta() {
if (isMetaClass()) return (Class)this;
else return this->ISA();
}
一目了然,系統(tǒng)獲取類方法就是通過(cls->getMeta()
)獲取元類的class_getInstanceMethod
實(shí)例方法司恳。并且如果該類為元類的話,就是獲取自己的實(shí)例方法途乃。所以,類方法信息應(yīng)該是存在元類中,我們可以驗(yàn)證一下
可以發(fā)現(xiàn),類方法的確存儲(chǔ)在元類中
拓展 - 面試 以下輸出結(jié)果是什么
//@interface Person : NSObject
//- (void)run;
//+ (void)find;
//@end
void getmethod (Class cls){
const char *className = class_getName(cls);
Class metaCls = objc_getMetaClass(className);
Method method1 = class_getInstanceMethod(cls, @selector(run));
Method method2 = class_getInstanceMethod(metaCls, @selector(run));
Method method3 = class_getClassMethod(cls, @selector(find));
Method method4 = class_getClassMethod(metaCls, @selector(find));
Method method5 = class_getInstanceMethod(metaCls, @selector(find));
NSLog(@"\nmethod1:%p\nmethod2:%p\nmethod3:%p\nmethod4:%p\nmethod5:%p\n",method1,method2,method3,method4,method5);
}
運(yùn)行結(jié)果如圖:
原因
-
實(shí)例方法
是存在對(duì)應(yīng)類
中,元類
中沒有,所以method1
找到,method2
沒找到。 -
類方法
存在元類
中,所以method5
能找到扔傅。 -
class_getClassMethod
本身是去元類
中找實(shí)例方法
,所以method3
能找到耍共。 -
元類
的class_getClassMethod
是在自身的實(shí)例方法
中找,所以method4
能找到。