app的启动过程分为两种:
-
冷启动
app的进程不在系统中,需要系统内核kernel创建进程。
-
热启动
app的进程在系统中,不需要创建进程,可以理解为是从后台切换到前台。
主要看下冷启动
启动流程
pre-main
-
加载所有的可执行文件
-
加载dyld
苹果动态链接器,dynamic loader,专门加载动态链接库的库
-
加载动态库
使用dyld,递归加载,最后调用
_objc_init。这个部分,可以看这篇文章iOS 底层探索 - 应用加载,写的很详细。👍 -
runtime组件的初始化
Class的注册、Category的注册、SEL唯一性检查等
-
其他初始化操作
+load(),C++静态全局变量等
通过设置Environment Variables中DYLD_PRINT_STATISTICS的value为1,增加环境变量,打印加载时间。
main() -> didFinish
rootVC,首屏文件的读写,数据的获取、计算,页面的渲染等
首屏结束
其他非主要模块的初始化
优化点
- 减少+load(),尽量放在渲染之后,可以使用+initialize替代,要注意避免多次调用+initialize(可以使用dispatch_once)
- 合并功能类似的类或扩展
- 合并动态库
- 移除不需要的动态库
- 移除不需要的类
- 减少C++全局变量
- 首屏完成之前,只处理首屏渲染相关的工作
- 优化主线程耗时操作,防止屏幕卡顿,采用异步处理
- 压缩资源图片,降低IO
注意⚠️:
- pre-main应该在400ms内完成加载
- 整体的过程不能超过20s,否则系统会kill进程
开屏广告优化
背景:需要展示网络图片或视频
方案一:等待网络图片或视频的下载完成
缺点:阻塞,如果时间过长,影响用户体验,
方案二:异步下载缓存,下次展示
app启动后,通过异步线程,获取图片或视频,下载到本地,本次不展示 再次启动app时,检查是否下载完成,如果已经存在,则展示,否则不展示
缺点:不能在本次app的启动时立马看到效果,在重要时刻,需要提前下载
关于dyld,可以看这篇文章dyld详解