如何检测iOS应用在后台运行时被系统终止?
iOS后台非挂起状态被系统终止的检测方案(附用户强制退出排除逻辑)
你说的这个困惑太真实了——applicationWillTerminate确实完全靠不住,不管是用户手动杀进程还是系统在后台硬终止App,这个方法都不一定会执行,尤其是App在后台非挂起(比如跑后台任务)的时候,系统可能直接下杀手,连回调的机会都不给。那怎么区分这两种情况呢?我给你分享几个实际项目里用过的思路:
先给后台活跃状态打个标记
当你的App进入后台并启动后台任务(比如调用beginBackgroundTask(expirationHandler:)),立刻在UserDefaults或者Keychain里存一个标记,比如isRunningBackgroundTask = true,顺便记录当前的时间戳。这个标记的作用是,下次启动时能知道App上次是在“干活”的状态下没的,不是正常退到后台挂着的。启动时校验标记+判断启动原因
等App下次启动(不管是用户点图标还是系统唤醒),先读这个标记:- 如果标记是
true,说明上次App是在后台活跃执行时被终止的; - 接下来区分是不是用户干的:iOS有个特性,要是用户强制杀了正在后台执行任务的App,系统在一段时间内不会主动唤醒它(比如推送、后台刷新都没用)。所以:
- 如果本次启动是系统触发的(比如收到推送、定位更新触发、后台刷新任务),那基本可以排除用户强制退出——毕竟用户杀了App后,系统不会没事把它拉起来;
- 如果是用户手动点图标启动的,就看时间差:如果上次后台任务的时间和本次启动时间间隔很短(比如几分钟内),有可能是用户杀的,但如果间隔很长,大概率是系统因为内存不足或者资源紧张给终止了。
- 如果标记是
记得及时清理标记
当后台任务正常结束(调用endBackgroundTask(_:)),或者App从后台回到前台时,一定要把那个标记改成false,不然下次启动会误判。
额外提醒:这种方法没办法做到100%精准,毕竟苹果没开放直接区分用户/系统终止的API,但这是目前能实现需求的最靠谱方案了,很多大厂的App也是这么做的。
内容的提问来源于stack exchange,提问作者Ata01




