本文对比一下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]发生了什么