本文共 1592 字,大约阅读时间需要 5 分钟。
简单来说,一个应用的启动过程是指,用户点击应用图标开始,到用户看到该应用的第一个界面为止。具体可以分为下面几个时间段:
用户点击应用图标~main函数执行前
在该阶段,系统会加载可执行文件(应用的 .o
文件集合),加载动态链接库,调整 rebase 指针并进行符合绑定。Objc 会初始化,包括 Objc 相关类的注册,分类(category)的注册以及选择器(selector)的唯一性检查等。并且,初始化时,各个类的 +load()
方法会被执行,且 C++ 静态全局变量会被声明等。
为减少应用启动时间,相应的可以减少动态库的加载,减少 C++ 全局变量的声明,移除无用的类或方法,+load()
中的操作可以延后的延后,或者放在 +initialize()
方法中执行。
main函数开始执行~首屏渲染之前
int main(int argc, char * argv[]){ @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([MyAppDelegate class])); }}- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ // Override point for customization after application launch. return YES;}
这个阶段实际是指从代理类的 application: didFinishLaunchingWithOptions
方法开始到所有与首屏渲染相关的代码执行完毕为止。这些代码执行的目的,可能会是去读取本地配置、请求服务器上的数据或者进行一些必要的计算等。
所以为了节省时间,应当将与首屏渲染无关的操作放在首屏渲染完成后。
首屏渲染完成后
这个阶段实际是指首屏渲染代码完成后到 application: didFinishLaunchingWithOptions
方法结束之前的所有操作,虽然这部分的操作并不会妨碍用户看到首屏,但是如果耗时太长,会使得主线程无法响应用户手势,造成界面卡顿。
所以这个阶段不宜存在大量计算或读写文件等耗时操作,可以单开一个线程执行相关操作。
类方法 +initialize() 与 +load()
+ (void)initialize;
当运行时第一次向一个类发送消息时,该方法便会被执行,并且该方法只自动执行一次且是线程安全的,其他线程向该类发送的消息都会被阻塞,直到初始化方法结束。
通常情况,不应该主动去调用该方法,但是也存在子类主动调用父类的初始化方法,所以可以使用下面的写法,来避免自己定义的初始化任务被重复执行。
+ (void)initialize { if (self == [ClassName self]) { // ... do the initialization ... }}
这里的 self
很特殊,虽然只声明了 - (instancetype)self;
实例方法,但是向类发送 self
消息也是不会报错的,原因可以参见 。
当类或者分类被加入到 Objective-C 运行时中时,可以实现下面的方法,对该类进行一些特殊处理,如 hook 处理。
+ (void)load;
初始化方法的执行的顺序为:
+load
方法C++
静态变量初始化以及被 __attribute__(constructor)
修饰的函数参考
转载地址:http://kvdws.baihongyu.com/