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

Swift iOS导航返回报错咨询:如何正确返回或跳转页面?

解决 "Attempt to present on whose view is not in the window" 问题及正确的页面跳转/返回方式

首先得帮你拆解下这个警告的核心原因:你当前调用present(_:animated:completion:)的那个视图控制器,它的视图已经不在App的窗口层级里了——要么是这个VC已经被dismiss掉,要么是它本身就没被正确添加到导航栈或窗口中,导致系统找不到它的视图来承载新弹出的控制器。

接下来针对你的场景,给出靠谱的返回和跳转方案:

一、正确的页面返回方式

如果你的ScoreViewController是通过present方式弹出来的,返回上一页的正确姿势是在当前的ScoreViewController实例里调用dismiss方法,别去操作已经被隐藏的原VC:

// 在ScoreViewController的按钮点击事件或逻辑里写
@IBAction func backButtonTapped(_ sender: UIButton) {
    dismiss(animated: true, completion: nil)
}

要是你的原VC是嵌入在导航控制器里的,也可以用导航栈的popViewController(animated:),但前提是你当初是用push而不是present跳转到ScoreVC的。

二、避免报错的正确跳转方式

你现在的跳转代码本身没问题,但要确保调用这段代码的VC是当前处于活跃状态、视图确实在窗口层级里的控制器。给你两个实用建议:

  1. 别在已经被dismiss的VC的异步回调(比如网络请求的completion)里调用这段代码——此时这个VC的视图早就不在窗口里了,自然会报错。
  2. 如果是在全局工具类或者非活跃VC里跳转,最好先获取当前窗口的最顶层可见控制器,再用它来present:
// 先写个工具方法获取最顶层可见控制器
func getTopVisibleViewController() -> UIViewController? {
    guard let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return nil }
    var topVC = keyWindow.rootViewController
    while let presentedVC = topVC?.presentedViewController {
        topVC = presentedVC
    }
    return topVC
}

// 然后用这个顶层控制器来跳转
if let topVC = getTopVisibleViewController(), 
   let scoreVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ScoreViewController") as? ScoreViewController {
    topVC.present(scoreVC, animated: true, completion: nil)
}

额外提醒

  • 尽量别在非活跃的VC(比如已经被dismiss、或者还没加载完成的VC)里执行页面跳转操作。
  • 如果你的页面结构是基于导航控制器的,优先用pushViewController(_:animated:)和popViewController(animated:)来管理页面栈,这样层级更清晰,也不容易踩窗口层级的坑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:48:50