讲讲 iOS 中鲜为人知的"预热启动"

这里每天分享一个 iOS 的新知识,快来关注我吧

启动类型

在 iOS 上,我们都清楚启动类型分为"热启动"和"冷启动"。

按照苹果的定义,如果你打开 App 后滑回到主屏幕并手动杀掉程序,然后立即重新打开 App,这种启动方式通常称为"热启动"。

如果你刚刚玩了一款需要使用大量内存的游戏,你的 App 可能会被系统杀掉,并清空你的 App 所占用的内存,以允许这个游戏拥有更多内存。然后你再次进入你的应用,那么它可能会比你的平均启动速度慢得多。你的应用程序所依赖的框架和进程也可能需要重新启动和从磁盘分页。这种情况,或者在手机重启后的启动,通常被称为冷启动。

还有一种严格意义上说不叫启动,就是从后台到前台,打开 App 后,先退到后台,再点击图标打开,这种情况一般称为"恢复"(resume)。

按照 WWDC 的这张图,可以很生动的看出,冷启动像乌龟速度最慢,热启动像兔子,速度次之,恢复像豹子,速度最快。

iOS 15 新增的启动类型

在 iOS 15 及更高版本中,系统会学习用户习惯,比如你几点经常打开某个 App,为了让你启动速度更快,在你打开之前,系统会先帮你把这个 App 进程启动并加入内存中,这就是苹果新增的一种启动类型,Prewarming Launch(预热启动)

按照苹果的文档,预热会启动 App 进程,直到(但不包括),main() 调用 UIApplicationMain。但是经过我的测试,预热启动不但会调用到 main 函数,甚至有时候会调用到 Appdelegate 中的 application(:, didFinishLaunchingWithOptions:) 方法。因此苹果的文档是不准确的(也可能是个 bug)。

预热启动带来的问题

虽然预热启动可以让启动速度更快,这的确提升了用户体验,但同时也带来了一些问题。

比如市面上很多 APM 工具,例如 FirebaseSentry 等,统计启动时间都是从进程启动到第一个页面展示出来,如果这次启动是预热启动,那么就可能导致启动时间出现非常大的误差,比如进程启动时间为早上 8 点,可能用户晚上 8 点才启动 App。

另一个问题是预热启动下有些 API 是无法正常调用的,比如钥匙串相关的 API 就无法正常调用,正如前面所说,预热启动下可能会走到 application(:, didFinishLaunchingWithOptions:) 方法,也就是说在这个方法调用的时候,之前所有访问钥匙串的代码可能都是无效的,比如你在 +load() 方法里访问了不能访问的 API,就会导致非预期的结果发生。

解决方案

这时候大家可能会想,如果可以知道这次启动是否为预热启动就好了,但是苹果并未提供相关的 API,但是国外有个 iOS 开发小哥发现苹果在环境变量中增加了一个名为"ActivePrewarm" 的字段来标记是否为预热启动,那么我们就可以顺利使用这个标记来知道是否为预热启动了:

bash 复制代码
if ProcessInfo.processInfo.environment["ActivePrewarm"] == "1" {
    print("本次启动为预热启动")
} else {
    print("本次启动为非预热启动")
}

可以尝试通过以下步骤测试预热启动:

  1. 启动你的 App

  2. 简单使用一会儿

  3. 强制退出 App

  4. 锁定设备,放置大概约 30 分钟

  5. 解锁设备

  6. 再次启动应用程序

以上步骤有概率复现预热启动的情况。

然后就可以根据是否为预热启动来分别解决上边提到的问题,衡量启动时间的时候可以把预热启动的情况过滤掉。

如果为预热启动,把无法正常调用的 API 放到启动成功之后。

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
子春一4 小时前
Flutter 与原生平台深度集成:打通 iOS 与 Android 的最后一公里
android·flutter·ios
依旧风轻4 小时前
objc_object 与 objc_class 是一定要了解的底层结构
ios·objective-c·isa·objc_class·objc_object
m0_495562787 小时前
Coreblutooth蓝牙
ios
00后程序员张8 小时前
HTTPS Everywhere 时代的抓包挑战,从加密流量解析到底层数据流捕获的全流程方案
网络协议·http·ios·小程序·https·uni-app·iphone
QuantumLeap丶9 小时前
《Flutter全栈开发实战指南:从零到高级》- 23 -混合开发与WebView
android·flutter·ios
lancoff9 小时前
#1 onLongPressGesture
ios·swiftui
2501_9159214314 小时前
Bundle Id 创建与管理的工程化方法,一次团队多项目协作中的流程重构
服务器·ios·小程序·重构·https·uni-app·iphone
2501_9159090616 小时前
深度解析 iOS 内存占用,构建多工具协同的内存诊断、监控与优化体系
android·ios·小程序·https·uni-app·iphone·webview
longforus17 小时前
Flutter iOS 真机部署异常经验(Android Studio 提示无法运行,但 Xcode 可正常运行)
flutter·ios·android studio