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

如何同时执行present与dismiss操作?当前代码仅完成dismiss无效果

解决dismiss后无法present新视图控制器的问题

嘿,我来帮你搞定这个问题!你现在遇到的情况是dismiss完成后present不生效,核心原因其实很简单——当dismiss执行完毕,你的当前视图控制器(也就是代码里的self)已经被移出视图层级了,它不再是当前活跃的控制器,这时候调用它的present方法自然不会有效果。

下面给你两种靠谱的解决方案:

方法一:找到当前应用的顶层视图控制器来present

我们可以通过扩展UIViewController,写一个方法来遍历找到当前最顶层的控制器,然后用它来present新的VC,这种方法适配性更强,不管当前控制器是被present还是push出来的都能用:

@IBAction func backButton(_ sender: UIButton) { 
    self.dismiss(animated: true, completion: { 
        let storyboard = UIStoryboard(name: "Main", bundle: nil) 
        // 建议用安全解包替代强制解包,避免崩溃
        guard let vc = storyboard.instantiateViewController(withIdentifier: "RequestItemPackageDetails") as? RequestItemPackageDetails else {
            print("无法获取目标视图控制器")
            return
        }
        
        // 获取顶层视图控制器并present
        if let topVC = UIApplication.shared.windows.first?.rootViewController?.topMostViewController() {
            topVC.present(vc, animated: true, completion: nil)
        }
    }) 
}

// 给UIViewController添加扩展,方便获取顶层VC
extension UIViewController {
    func topMostViewController() -> UIViewController {
        if let presentedVC = self.presentedViewController {
            return presentedVC.topMostViewController()
        }
        return self
    }
}

方法二:用当前控制器的presentingViewController来present

如果你的当前控制器是被另一个父控制器present出来的,那在dismiss之后,父控制器会回到前台,这时候我们可以提前保存这个父控制器,在completion里用它来present新VC:

@IBAction func backButton(_ sender: UIButton) { 
    // 提前保存presentingViewController,避免闭包中出现nil或者循环引用问题
    guard let presentingVC = self.presentingViewController else {
        // 如果没有presentingViewController,直接dismiss即可
        self.dismiss(animated: true)
        return
    }
    
    self.dismiss(animated: true, completion: { 
        let storyboard = UIStoryboard(name: "Main", bundle: nil) 
        guard let vc = storyboard.instantiateViewController(withIdentifier: "RequestItemPackageDetails") as? RequestItemPackageDetails else {
            print("无法获取目标视图控制器")
            return
        }
        presentingVC.present(vc, animated: true, completion: nil)
    }) 
}

额外提醒

  • 尽量不要用as!强制解包,万一storyboard里的标识符写错或者类型不匹配,会直接导致崩溃,用guard let或者if let做安全处理更稳妥。
  • 如果你的当前控制器是通过导航栈push出来的,那self.presentingViewController会是nil,这时候就必须用第一种方法啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:32:36