本文要是要针对启动优化相关概念和最佳实践的介绍。

什么是启动
首先来看一下启动类型都有哪几种,以及每种启动类型的特点。

启动类型
共有三种启动类型,分别为:冷启动、热启动和重新启动,下面为它们的特点。

冷启动
重启之后。
APP 未在 iPhone 的内存中。
APP 线程不存在。
热启动
最近被终止的。
APP 部分在内存中。
APP 线程不存在。
重新启动
APP 被暂停(比如按下 home 键)。
整个 APP 都在内存中。
APP 线程存在。
介绍完启动类型,下面来看一下启动共分为几个阶段以及每个阶段的应该避免的做法。

启动的六大阶段
六大阶段分别为:系统接口初始化(System Interface)、Runtime 初始化、UIKit 初始化、Application 初始化、初始化第一帧、扩展(Extended)。

先看下每个阶段都具体做了哪些事情。

System Interface:初始化底层的系统接口、系统部分的工作花费固定的时间,也就是说该阶段的系统部分是不用我们操心的。
Runtime Init:初始化语言的运行时环境、调用所有类的静态 load 方法。
UIKit Init:实例化 UIApplication 和 UIApplicationDelegate、开始事件处理和系统集成。
Application Init:调用 UIApplicationDelegate/UISceneDelegate 生命周期的回调,比如:application:willFinishLaunchingWithOptions:。
Initial Frame Render:创建、执行布局,并绘制视图;提交渲染第一帧。loadView/viewDidLoad/layoutSubviews
Extended:该阶段为显示第一帧后的特定时间,该阶段会异步加载数据,你的 APP 在当前阶段应该是可交互、可响应的。
下面看下每个阶段应该避免的做法。

System Interface
避免连接没用的 framework。
避免在启动阶加载动态库。
硬链接所有的依赖。
Runtime Init
减少 +load 方法的调用。
使用 +initialize 去懒加载静态初始化。
暴露 framework 中的初始化 API。
UIKit Init
减少 UIApplication 子类的工作。
减少 UIApplicationDelegate 初始化的工作。
Application Init
延后 UIApplicationDelegate 生命周期中不相关的工作。
两个 scenes 之间共享资源。
Initial Frame Render
减少视图层级,懒加载视图。
使用高性能的自动布局。
Extended
应使用 os_signpost 去检测耗时代码。
介绍完启动类型和启动阶段,接下来看一下如何正确的测量。

正确的测量启动
在进行启动时间测量时,应对多次测量环境保持干净一致的测量环境,这样测量的结果才会有说服力。

可以通过下面的方法来保持环境的一致性:

重启手机,并放置2-3min。
启动飞行模式或者 mock 环境。
不使用 iCloud 账户,或者使用一致的 iCloud 账户。
使用 App 的 release 模式。
测量热启动。
在测量过程中我们应对新旧设备都进行测试。

启动时间可以通过 XCTest 来进行测试。
截屏2021-05-10 下午4.53.33.png
如何优化启动时间
主要通过下面的三大块来优化。

减少工作量
延后与第一帧不相关的工作。比如 application:willFinishLaunchingWithOptions: 里不重要的接口调用。
移除阻塞主线层的代码。耗时的操作肯定要放在子线程异步处理。
减少内存的使用。
指定正确的优先级
这一块主要针对正确的使用 GCD。

对于 task 使用正确的 Qos。
利用 scheduler 来优化启动。
使用正确的原语优先级。
优化代码
简化已有代码。
使用正确的数据结构和算法。
缓存一切可缓存的。
总结
优化启动时间很重要,我们要让它成为日常开发的一部分。
删除一切不需要的代码合资源。
正确的使用 GCD、数据结构和算法。
重构简化现有代码。
尽可能多的缓存。

点击可获取iOS资料大全