Skip to content

initialize

ShenYj edited this page Mar 2, 2022 · 4 revisions

initialize

initialize 方法是在类或它的子类收到第一条消息之前被调用的,这里所指的消息包括实例方法和类方法的调用。也就是说 initialize 方法是以懒加载的方式被调用的,如果程序一直没有给某个类或它的子类发送消息,那么这个类的 initialize 方法是永远不会被调用的。那这样设计有什么好处呢?好处是显而易见的,那就是节省系统资源,避免浪费。

runtime 使用了发送消息 objc_msgSend 的方式对 initialize 方法进行调用。也就是说 initialize 方法的调用与普通方法的调用是一样的,走的都是发送消息的流程。换言之,如果子类没有实现 initialize 方法,那么继承自父类的实现会被调用;如果一个类的分类实现了 initialize 方法,那么就会对这个类中的实现造成覆盖。

  • 调用时机:

    • 类在第一次接到的消息的时候调用,每一个类只会initialize一次

      如:[Person alloc],就会调用一次,并且后面再 alloc 也不会调用

  • 调用顺序:

    • 先调用父类的initialize
    • 再调用原类的initialize
      • 如果原类有分类,并且分类重写initialize,则会调用分类中的initialize(按着编译的反顺序,越后编译越先被执行, 源码的处理方式是插入到方法列表的前部)
      • 当子类没有initialize,会调用父类的 initialize,父类可能被调用多次
      • e.g. 父类Person,实现 initialize,两个子类 Student、Teacher,分别继承自Person,未实现 initialize
        当初始化Student、Teacher后就会发现 Person的 initialize 被调用了三次

        1. 当类第一次收到消息时,首先会优先检查当前类(这里指子类)是否初始化,没有初始化在对当前类发送 initialize 消息前,递归检查父类有没有初始化(处理过程与load有些相似,不过 load 是方法地址直接调用),此时 Person 肯定也没有初始化,因此会执行两次 msgSend,分别是 Person 和 子类(假设为Student)
        2. 另外一个子类也会做同样的检查,但是此刻Person已经被标记为初始化,因此只有一次msgSend -> 当前子类(假设为Teacher)
        3. 由于initialize 走的是消息发送机制,通过isa找到元类对象发现自己没实现initialize,会顺着superclass向上查找,找到父类Person,所以三次msgSend都触发了父类 initialize 被调用
  • initialize 方法调用流程

    lookUpImpOrForward -> realizeAndInitializeIfNeeded_locked -> initializeAndLeaveLocked -> initializeAndMaybeRelock -> initializeNonMetaClass -> callInitialize -> initialize

    initialize 方法在第一次消息发送的时候才调用,所以并不会影响类和分类的加载情况

.

Getting Started

Social

Clone this wiki locally