本文对比一下iOS中的alloc、init、load、initialize方法分别做了什么

1. - alloc

alloc方法是实例方法。alloc方法负责创建对象,这个过程包括:

  • 分配足够的内存来保存对象
  • 写入isa指针
  • 初始化引用计数
  • 重置对象中的所有实例变量

alloc方法会返回一个未被初始化的对象实例

 

2. - init

init方法是实例方法。负责初始化对象

  • 对象在执行init方法后处于可用状态,即对象的实例变量可以被赋予合理有效值,这也是在自定义init方法时要先调用父类的init方法的原因。
  • 子类初始化时,会先调用父类的初始化方法,然后调用自身的-init()方法,并且每次初始化都会调用
  • 子类未实现-init()方法时,每初始化一个对象,只会调用一次父类的-init()方法

 

3. + load

load方法是类方法。其主要特点有:

  • 调用在main()函数之前,并且不会主动调用,程序启动会把所有的文件加载,文件如果重写了+load()方法,主类、子类、分类(category)都会加载调用+load()方法
  • 调用顺序:主类 > 子类 > 分类
  • 分类间的加载顺序取决于编译的顺序,先编译的先加载,后编译的后加载
  • 因为+load()方法在main()函数之前调用,所以在这个方法中不宜做耗时或者阻塞操作,会影响启动速度
  • 不要在+load()方法中做对象的初始化操作,因为+load()方法在main()函数之前自动调用,此时使用者根本就不能确定自己要使用的对象是否已经加载进来了
  • 可以根据业务需求,在+load()方法中进行Method Swizzle操作,替换方法的默认实现

    

4. + initialize

initialize方法是类方法。

  • initialize方法在类或者它的子类收到第一条消息之前被调用。这里所指的消息包括实例方法和类方法,也就是说+initialize()方法是以懒加载的方式调用的,若程序一直没有给某个类或它的子类发送消息,那么这个类的+initialize()方法是永远不会被调用的
  • 父类的+initialize()方法会比子类先执行

 

总结:

  • +load()和+initialize()都会在实例化对象之前调用,前者是在main()函数之前,后者是在main()函数之后
  • +load()和+initialize()方法都不会显式地调用父类的方法而是自动调用,即使子类没有+initialize()方法也会调用父类的方法,+load()方法不会调用父类方法;
  • +load()和+initialize()方法内部使用了锁,因此他们是线程安全的,实现时要尽可能简单,避免线程阻塞,不要再次使用锁
  • +load()方法常用来method swizzle,+initialize()常常用于初始化全局变量和静态变量

 

参考:

iOS:浅谈 +load()、+initialize()、-init()

OC中[NSObject alloc] init]发生了什么