load和initialize的共性
- 1.都是为了应用运行提前创建合适的运行环境在不考虑开发者主动使用的情况下,系统最多会调用一次
- 2.在不考虑开发者主动使用的情况下,系统最多会调用一次
- 3.方法的执行顺序是先父类后子类
- 4.在使用时都不要过重地依赖于这两个方法,除非真正必要
load的相关特点
1.运行时机
load
的执行时机在App
启动时,而且是在main()
之前,但并不能保证所有类都加载完成且可用。因此此时C++
静态初始化程序还没有运行,但你链接到的framework
在此点确保完全加载了。
2.加载的内容
你链接的framework
->镜像中的所有load
方法->镜像中所有C++
静态初始化和C/C++attribute(构造函数)
函数->链接到你的framework
3.执行顺序
一个类的load
方法不用写明[super load]
,父类也会执行load
方法,并且是先父类后子类的顺序。
Category
的load
方法也会执行,并且是先类后分类的顺序。
4.在Category中的特性
load
方法在category
中的使用有另外一个特性。对于某个类,当category
中重写某个方法时,只会执行category
中的此方法,并不会执行原类中的此方法。但在category
中重写load
方法后并不会影响其原来类的load
方法执行,而是如上面所说的先类后分类的顺序执行。
5.autorelease
在load
中必要时还要自己负责做autorelease
处理
6.swift中的load
桥接到Objective-C
的Swift
类的加载方法的自定义实现不会自动调用。
7.源码
你可以看到在运行时如何查找的load
方法作为一种特殊情况_class_geLoadMethod
的objc-runtime-new.mm
,并直接调用它call_class_loads的objc-loadmethod.mm
initialize的相关特性
1.运行时机
在收到第一条消息之前初始化该类,初始化每个类只调用一次。与load
的加载时机不相同,类似于懒加载的方法,所以也可能根本不会被调用。
当一个类首次加载时,+initialize
不调用。当消息发送到一个类时,运行时首先检查是否+initialize
已经被调用。如果没有,则在继续发送消息之前调用它。
2.执行顺序
顺序为先父类后子类,所以超类在他们的子类之前收到这个消息。
3.父类和子类
和load
不同,如果子类不实现initialize
,或者如果子类明确调用[super initialize]
,则可以多次调用超类实现。如果要保护自己不要多次运行,可以按照以下方式构建您的实现:
+ (void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
4.线程安全
运行时以线程安全的方式将初始化消息发送给类。也就是说,初始化由第一个线程运行以将消息发送到类,并且尝试向该类发送消息的任何其他线程将阻塞,直到初始化完成。所以initialize
的运行过程中是能保证线程安全的。
5.运行环境
与load
不同,load
的运行环境还是相对比较危险的,而在initialize方法收到调用时,运行环境已经基本健全了。所以,initialize
的适用场景要比load
多。
6.源码
运行时initialize
在_class_initialize
函数中发送消息objc-initialize.mm
。您可以看到它用于objc_msgSend
发送它,这是普通的消息发送功能。
网友评论