1. 冷启动与热启动
冷启动
App点击启动前,此时App的进程还不在系统里。需要系统新创建一个进程分配给App。(完整的App启动过程)
热启动
App在冷启动后用户将App退回后台,此时App的进程还在系统里。用户重新返回App的过程。(热启动做的事较少)
2. App 完整启动流程
main()函数执行前main()函数执行后(从main函数执行,到设置self.window.rootViewController执行完成)- 首屏渲染完成后(从
self.window.rootViewController执行完成到didFinishLaunchWithOptions:方法作用域结束)
1. main函数执行前
- 加载可执行文件。(可执行文件是指 Mach-O 格式的文件,也就是App中所有.o文件的集合体)这一阶段dyld会分析应用依赖的
dylib,找到其mach-o文件,打开和读取这些文件并验证其有效性,接着会找到代码签名注册到内核,最后对dylib的每一个segment调用mmap()。 - 加载动态链接库,进行
rebase指针调整和bind符号绑定。 ObjC的runtime初始化。包括:ObjC相关Class的注册、category注册、selector唯一性检查等。- 执行
+(void)load方法;然后再执行 main 函数。
2. main函数执行后
从 main 函数执行开始,到 appDelegate 的 didFinishLaunchingWithOptions:方法里首屏渲染相关方法执行完成。
执行 UIApplicationMain
- 根据传递的类名创建 UIApplication 对象,这是第一个对象
- 根据传递的 appDelegateClassName 创建 UIApplication 代理对象,并给 UIApplicaiton 对象设置代理
- 读取配置文件info.plist,设置程序启动的一些属性
- 开启主运行循 Runloop
- 通知应用程序代理,应用程序启动完毕
3. 首屏渲染完成后
didFinishLaunchingWithOptions方法作用域内执行首屏渲染后的所有方法执行。即, 从设置self.window.rootViewController到didFinishLaunchWithOptions:方法作用域结束。
3. 启动优化
main函数执行前
减少使用 +load() 方法
- 尽量将
+load中的内容,放到渲染完成后做。 - 使用
+initialize()的方法代替+load(),注意把逻辑移动到+initialize()时,要注意避免+initialize()的重复调用问题,可以使用dispatch_once()让逻辑只执行一次。
减少或者合并动态库
减少依赖不必要的库,不管是动态库还是静态库;如果可以的话,把动态库改造成静态库;如果必须依赖动态库,则把多个非系统的动态库合并成一个动态库;
苹果公司建议使用更少的动态库,并且建议在使用动态库的数量较多时,尽量将多个动态库进行合并。数量上,苹果公司最多可以支持6个非系统动态库合并为一个。
优化类、方法、全局变量
减少加载启动后不会去使用的类或方法;少用C++全局变量;
main函数执行后
优化首屏渲染前的功能初始化
减轻 [UIApplication appDidFinishLaunchWithOptions:] 业务量,可以尝试将重的业务置于异步线程
main 函数执行后到首屏渲染完成前,只处理首屏渲染相关业务。首屏渲染外的其他功能放到首屏渲染完成后去初始化。
优化主线程耗时操作,防止屏幕卡顿。
首先检查首屏渲染前,主线程上的耗时操作。将耗时操作滞后或异步处理。通常的耗时操作有:网络加载、编辑、存储图片和文件等资源。针对耗时操作做相对应的优化即可。