AI智能
改变未来

iOS:底层原理之 +load & +initialize


+load 方法

  • +load 方法会在 runtime 加载类、分类的时候调用
  • 每个类、分类的 +load,在程序运行过程中只调用一次
  • 可以理解为加载入内存时调用。

调用顺序

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

    objc4 源码解读过程:objc-os.mm

    • _objc_init

    • load_images

    • 1.prepare_load_methods

      schedule_class_load

    • add_class_to_loadable_list
    • add_category_to_loadable_list
  • 2.call_load_methods

      call_class_loads
    • call_category_loads
    • (*load_method)(cls, SEL_load)
  • +load 方法是根据方法地址直接调用,并不是经过 objc_msgSend 函数调用

  • [Person load]; 此种调用方式一定会出发 objc_msgSend ( )。isa->superclass->superclass

    +initialize 方法

    • +initialize 方法会在类第一次接收到消息时调用 objc_msgSend( )。
    • 调用顺序:先调用父类的 +initialize 方法,再调用子类的 +initialize 方法

    objc_msgSend( )

    isa -> 类对象/元类对象,寻找方法,调用
    supclass -> 类对象/元类对象,寻找方法,调用
    supclass -> 类对象/元类对象,寻找方法,调用
    supclass -> 类对象/元类对象,寻找方法,调用
    … …

    +load 方法,在此类加载到内存中时调用。
    +initialize 方法是在寻找方法的时候进行调用,在第一次使用此类的时候想做的事情可以在此方法中处理。

    objc4源码解读过程

    • objc-msg-arm64.sobjc_msgSend
  • objc-runtime-new.mm
      class_getInstanceMethod
    • lookUpImpOrNil
    • lookUpImpOrForward
    • if (initialize && !cls->isInitialized()) { cls = initializeAndLeaveLocked(cls, inst, runtimeLock);
    • initializeAndLeaveLocked
    • initializeAndMaybeRelock
    • initializeNonMetaClass(nonmeta);
    • callInitialize
    • objc_msgSend(cls, SEL_initialize)

    +load & +initialize 区别

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

    • 如果子类没有实现 +initilize 方法,会调用父类的 +initilize 方法(所以父类的 +initilize 可能会被调用多次)
    • 如果分类实现了 +initilize 方法,就覆盖类本身的 +initilize 调用。
    • 点赞
    • 收藏
    • 分享
    • 文章举报

    GS-NICE发布了177 篇原创文章 · 获赞 0 · 访问量 2698私信关注

  • 赞(0) 打赏
    未经允许不得转载:爱站程序员基地 » iOS:底层原理之 +load & +initialize