You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift切换控制器报错:过渡中解散展示控制器及界面点击失效

问题解决建议

核心原因

直接替换window.rootViewController时,未正确清理A→B→C的present控制器层级,残留的presentation控制器、未完成的过渡操作(如Alert的present/dismiss)与新的root切换冲突,同时原present栈的视图可能未被移除,遮挡了A的视图导致点击失效。


方案1:通过present层级直接dismiss回A(推荐)

利用present控制器的层级关联,从C直接dismiss到A并添加过渡动画,彻底清理present栈:

// 在C控制器中执行
guard let bVC = presentingViewController, let aVC = bVC.presentingViewController else { return }

UIView.transition(with: UIApplication.shared.keyWindow!, duration: 0.3, options: .transitionCrossDissolve, animations: {
    self.dismiss(animated: false)
}, completion: { _ in
    aVC.view.window?.makeKeyAndVisible()
})

方案2:清理present栈后再替换rootViewController

若必须替换rootViewController,需先完整dismiss所有present的控制器:

// 在C控制器中执行
self.dismiss(animated: false) {
    self.presentingViewController?.dismiss(animated: false) {
        guard let window = UIApplication.shared.keyWindow else { return }
        let targetAVC = // 你的A控制器实例
        UIView.transition(with: window, duration: 0.3, options: .transitionCrossDissolve, animations: {
            window.rootViewController = targetAVC
        }, completion: { _ in
            window.makeKeyAndVisible()
        })
    }
}

注:如果A本身是初始rootViewController,无需重新赋值,仅清理present栈即可。


额外修复点

  • 消除Alert相关报错:检查B/C控制器中是否存在延迟执行的Alert弹出逻辑(如DispatchQueue.main.asyncAfter),需在控制器viewWillDisappear中取消这类任务,避免从已detached的控制器present弹窗。
  • 修复点击失效:若视图仍存在遮挡,可通过Xcode的Debug View Hierarchy工具排查,必要时手动清理残留视图:
// 紧急清理残留视图(优先用规范dismiss)
guard let window = UIApplication.shared.keyWindow else { return }
window.subviews.forEach { subview in
    if subview != window.rootViewController?.view {
        subview.removeFromSuperview()
    }
}

内容的提问来源于stack exchange,提问作者solitary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 19:32:33