iOS开发中总能看到+load和+initialize的身影,网上对于这两个方法有很多解释,官方也有说明,但有些细节不够清楚,今天我们来详细扒一扒这两个方法.
load
Apple文档是这样描述的
|
|
文档地址:https://developer.apple.com/reference/objectivec/nsobject/1418815-load?language=objc
load函数调用特点如下:
当类被引用进项目的时候就会执行load函数(在main函数开始执行之前),与这个类是否被用到无关,每个类的load函数只会自动调用一次.由于load函数是系统自动加载的,因此不需要调用父类的load函数,否则父类的load函数会多次执行。
- 当父类和子类都实现load函数时,父类的load方法执行顺序要优先于子类
- 当子类未实现load方法时,不会调用父类load方法
- 类中的load方法执行顺序要优先于类别(Category)
- 当有多个类别(Category)都实现了load方法,这几个load方法都会执行,但执行顺序不确定(其执行顺序与类别在Compile Sources中出现的顺序一致)
- 当然当有多个不同的类的时候,每个类load 执行顺序与其在Compile Sources出现的顺序一致
initialize:
Apple文档是这样描述的
|
|
文档地址:https://developer.apple.com/reference/objectivec/nsobject/1418639-initialize?language=objc
initialize函数调用特点如下:
initialize在类或者其子类的第一个方法被调用前调用。即使类文件被引用进项目,但是没有使用,initialize不会被调用。由于是系统自动调用,也不需要再调用 [super initialize] ,否则父类的initialize会被多次执行。假如这个类放到代码中,而这段代码并没有被执行,这个函数是不会被执行的。
- 父类的initialize方法会比子类先执行
- 当子类未实现initialize方法时,会调用父类initialize方法,子类实现initialize方法时,会覆盖父类initialize方法.
- 当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)
什么情况下使用
+load
由于调用load方法时的环境很不安全,我们应该尽量减少load方法的逻辑。另一个原因是load方法是线程安全的,它内部使用了锁,所以我们应该避免线程阻塞在load方法中
load很常见的一个使用场景,交换两个方法的实现
|
|
+initialize
initialize方法主要用来对一些不方便在编译期初始化的对象进行赋值。比如NSMutableArray这种类型的实例化依赖于runtime的消息发送,所以显然无法在编译器初始化:
|
|
总结
+load方法要点
当类被引用进项目的时候就会执行load函数(在main函数开始执行之前),与这个类是否被用到无关,每个类的load函数只会自动调用一次.由于load函数是系统自动加载的,因此不需要再调用[super load],否则父类的load函数会多次执行。
1. 当父类和子类都实现load函数时,父类的load方法执行顺序要优先于子类
2. 当一个类未实现load方法时,不会调用父类load方法
3. 类中的load方法执行顺序要优先于类别(Category)
4. 当有多个类别(Category)都实现了load方法,这几个load方法都会执行,但执行顺序不确定(其执行顺序与类别在Compile Sources中出现的顺序一致)
5. 当然当有多个不同的类的时候,每个类load 执行顺序与其在Compile Sources出现的顺序一致
注意: load调用时机比较早,当load调用时,其他类可能还没加载完成,运行环境不安全. load方法是线程安全的,它使用了锁,我们应该避免线程阻塞在load方法.
+initialize方法要点
initialize在类或者其子类的第一个方法被调用前调用。即使类文件被引用进项目,但是没有使用,initialize不会被调用。由于是系统自动调用,也不需要显式的调用父类的initialize,否则父类的initialize会被多次执行。假如这个类放到代码中,而这段代码并没有被执行,这个函数是不会被执行的。
1. 父类的initialize方法会比子类先执行
2. 当子类不实现initialize方法,会把父类的实现继承过来调用一遍。在此之前,父类的方法会被优先调用一次
3. 当有多个Category都实现了initialize方法,会覆盖类中的方法,只执行一个(会执行Compile Sources 列表中最后一个Category 的initialize方法)
注意: 在initialize方法收到调用时,运行环境基本健全。 initialize内部也使用了锁,所以是线程安全的。但同时要避免阻塞线程,不要再使用锁