回退 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:
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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user