OC

load方法和initialize方法的区别

Posted by sunzhongliang on September 17, 2019

load方法

我们创建两个类,分别是Person类和Student类,Student类继承Person类, 然后再分别创建Person和Student的category类。

分类里面有没有load方法?

Student类或者Person类中添加load方法,是可以执行的,证明分类当中可以有load方法

load方法什么时候调用?

load方法会在runtime加载类、分类时自动调用。默认情况下会调用一次,但手动调用也是可以调用成功的,如[Student load];

load方法的调用顺序

  • 先调用类本身的+load,调用时按照以下顺序:
    • 按照编译先后顺序调用(先编译,先调用;按照Xcode Build Phases中的Compile Sources顺序)
    • 如果有继承关系,则先调用父类的+load,再调用子类的+load
  • 再调用分类的+load
    • 按照编译先后顺序调用(先编译,先调用)

load方法的本质

通过Runtime方法把类的所有方法打印出来看看到底生成了什么方法

- (void)printMethodNamesOfClass:(Class)cls
{
    unsigned int count;
    // 获得方法数组
    Method *methodList = class_copyMethodList(cls, &count);
    
    // 存储方法名
    NSMutableString *methodNames = [NSMutableString string];
    
    // 遍历所有的方法
    for (int i = 0; i < count; i++) {
        // 获得方法
        Method method = methodList[i];
        // 获得方法名
        NSString *methodName = NSStringFromSelector(method_getName(method));
        // 拼接方法名
        [methodNames appendString:methodName];
        [methodNames appendString:@", "];
    }
    
    // 释放
    free(methodList);
    
    // 打印方法名
    NSLog(@"%@ %@", cls, methodNames);
}

打印发现,分类的方法和类本身的方法,都在类对象或者是元类对象里面,还是会和类自身的方法合并在一起

查看objc运行时源码: +load方法是根据方法地址直接调用,并不是经过objc_msgSend函数调用

objc源码阅读顺序:

initialize方法

initialize方法什么时候调用?

+initialize方法会在类第一次接收到消息时调用, 比如调用alloc方法

initialize方法调用顺序

  • 先调用父类的+initialize,再调用子类的+initialize
  • 先初始化父类,再初始化子类,每个类只会初始化1次(比如Student类和Teacher类继承自Person类,分别都实现了initialize方法,先调用Student类,然后再调用Teacher的alloc,这时候方法的调用顺序如下:
    1. 先调用Person类的initialize方法
    2. 在调用Student的initialize方法
    3. 然后再调用Teacher的initialize方法,因为调用Student的alloc时已经初始化了父类的initialize方法)

+initialize和+load的区别

+initialize是在类第一次接收到消息时调用,而+load方法是Runtime加载类的时候自动调用。 +initialize是通过objc_msgSend进行调用的

  • 如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次;比如Student类继承自Person类,假如Student类没有实现+initialize,当给Student类发送消息时,会调用两次+initialize方法,一次是Person对象调用, 一次是Student对象调用)
  • 如果分类实现了+initialize,就覆盖类本身的+initialize调用

本文首次发布于 孙忠良 Blog, 作者 [@sunzhongliang] , 转载请保留原文链接.