回退 IPA 升级自动 exit(0):itms-services 安装弹窗需 source app 在内存中

【bug】
上个 commit (b548039) 在跳 Safari 后等 didEnterBackground 自动 exit(0),
实测后果是 iOS 系统级"安装"确认弹窗根本不弹了 —— 整个升级链路被悄悄中断。

【根因】
iOS 的 itms-services:// URL scheme 启动系统安装确认弹窗时,依赖 source app
仍在内存里(安全机制:只允许有效 source app 触发系统级安装流程)。我们提前
exit 后,Safari 收到 URL 但系统拒绝弹确认窗。

【方案】
不再自动 exit。让 App 自然留在后台,iOS 在 IPA 替换时会自动结束旧进程
(或要求用户上滑),无需主动介入。

【UX】
alert 文案重新写成"前往下载"+"安装确认弹窗出现后请点击「安装」,等待下载
完成即可自动替换",对齐 iOS 实际安装流程。

代码注释里写清楚为什么不能 exit,避免未来再踩同一坑。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
joywayer
2026-06-27 21:19:37 +08:00
co-authored by Claude Opus 4.7
parent b54803966a
commit 74d478f5ac
@@ -549,35 +549,23 @@ public final class WebContainerViewController: UIViewController {
}
private func showIPAUpgradeAlert(downloadURL: String) {
// Safari exit(0)
// iOS itms-services:// source app
// exit Safari URL
//
//
// Safari App Safari
// iOS IPA App
//
let alert = UIAlertController(
title: "需要升级",
message: "检测到新版本,确认后将跳转下载并自动退出当前 App",
message: "检测到新版本,点击「前往下载」开始更新。\n\n安装确认弹窗出现后请点击「安装」,等待下载完成即可自动替换",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "确定", style: .default) { _ in
guard let url = URL(string: downloadURL) else { return }
// Safari "" IPA iOS App
// App / active"" kill
//
// Safari App didEnterBackground exit(0)
// - = iOS active inactive background exit crash
// - exit(0) "退" / Springboard crash
// - observer remove Safari 退退
var observerHandle: NSObjectProtocol?
observerHandle = NotificationCenter.default.addObserver(
forName: UIApplication.didEnterBackgroundNotification,
object: nil,
queue: .main
) { _ in
if let h = observerHandle {
NotificationCenter.default.removeObserver(h)
}
// iOS 0.3s "" SIGTERM
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
exit(0)
}
alert.addAction(UIAlertAction(title: "前往下载", style: .default) { _ in
if let url = URL(string: downloadURL) {
UIApplication.shared.open(url)
}
UIApplication.shared.open(url)
})
present(alert, animated: true)
}