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

+load 方法

  • +load 方法会在 runtime 加载类、分类的时候调用
  • 每个类、分类的 +load,在程序运行过程中只调用一次
  • 可以理解为加载入内存时调用。
调用顺序
  1. 先调用类的 +load
    1. 按照编译先后顺序调用(先编译,先调用)
    2. 调用子类的 +load 之前会先调用父类的 +load
  2. 再调用分类的 +load
    1. 按照编译顺序调用(先编译,先调用)
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.s
    • objc_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 调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值