消失的类方法
在类结构中,我们说了如何通过地址偏移查找类相关信息。但是,如果我们在Person类中添加一个类方法,你会发现无法在类信息中找到。
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
- (void)run;
+ (void)find;
@end
@implementation Person
- (void)run {
};
+ (void)find {
};
通过上一章的方法查看methods,无法找到类方法+(void)find

类方法获取
Runtime中为我们提供了获取方法的函数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();
}
一目了然,系统获取类方法就是通过(cls->getMeta())获取元类的class_getInstanceMethod实例方法。并且如果该类为元类的话,就是获取自己的实例方法。所以,类方法信息应该是存在元类中,我们可以验证一下

可以发现,类方法的确存储在元类中
拓展 - 面试 以下输出结果是什么
//@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);
}
运行结果如图:

原因
-
实例方法是存在对应类中,元类中没有,所以method1找到,method2没找到。 -
类方法存在元类中,所以method5能找到。 -
class_getClassMethod本身是去元类中找实例方法,所以method3能找到。 -
元类的class_getClassMethod是在自身的实例方法中找,所以method4能找到。