+load和+initialize方法调用时机

一、+load方法什么时候调用

+load方法会在runtime加载类、分类时调用(程序运行起来会先去加载调用+load 跟你引用没有引用其头文件没有关系)。
每个类、分类的+load,在程序运行过程中只调用一次

调用顺序:

  1. 先调用类的+load

    • 按照编译先后顺序调用(先编译,先调用)
    • 调用子类的+load之前会先调用父类的+load
  2. 再调用分类的+load

    • 按照编译先后顺序调用(先编译,先调用)

 

+load和+initialize方法调用时机

 

 

二、为什么原本类的+load方法不会被分类的+load方法覆盖呢?

这是由于+load方法是根据方法地址直接调用,并不是经过objc_msgSend函数调用

+load方法相关源码阅读顺序:

  1. _objc_init
  2. load_images
  3. prepare_load_methods
    • schedule_class_load
    • add_class_to_loadable_list
    • add_category_to_loadable_list
  4. calls
    • call_class_loads
    • call_category_loads
    • (*load_method)(cls, SEL_load)

 

三、+initialize方法调用的时机

+initialize方法会在类第一次接收到消息时调用。

调用顺序:先调用父类的+initialize,再调用子类的+initialize,每个类只会初始化1次

+initialize方法相关源码阅读顺序:

  1. objc-msg-arm64.s

    • objc_msgSend
  2. objc-runtime-new.mm

    • class_getInstanceMethod
    • lookUpImpOrNil
    • lookUpImpOrForward
    • _class_initialize
    • callInitialize
    • objc_msgSend(cls, SEL_initialize)

+initialize和+load的最大区别是,+initialize是通过objc_msgSend进行调用的,所以有以下特点:

  • 如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次)
  • 如果分类实现了+initialize,就覆盖类本身的+initialize调用

 

四、总结

load、initialize方法的区别什么?
1.调用方式
1> load是根据函数地址直接调用
2> initialize是通过objc_msgSend调用

2.调用时刻
1> load是runtime加载类、分类的时候调用(只会调用1次)
2> initialize是类第一次接收到消息的时候调用,每一个类只会initialize一次(父类的initialize方法可能会被调用多次)

load、initialize的调用顺序?
1.load
1> 先调用类的load
a) 先编译的类,优先调用load
b) 调用子类的load之前,会先调用父类的load

2> 再调用分类的load
a) 先编译的分类,优先调用load

2.initialize
1> 先初始化父类
2> 再初始化子类(可能最终调用的是父类的initialize方法)

 

发表评论

评论已关闭。

相关文章