消失的类方法
在类结构中,我们说了如何通过地址偏移查找类相关信息。但是,如果我们在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
能找到。
网友评论