OC底层05.1:类方法生成位置

消失的类方法

在类结构中,我们说了如何通过地址偏移查找类相关信息。但是,如果我们在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_getInstanceMethodclass_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能找到。

你可能感兴趣的:(OC底层05.1:类方法生成位置)