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

视图控制器A被模态呈现或Push时,如何正确回退至对应来源控制器?

解决视图控制器A的回退判断问题

这个场景我之前做项目时也碰到过,确实只靠presentingViewController只能处理模态跳转的情况,导航栈里的push跳转根本吃不到这个属性,给你几个实用的解决思路:

方案1:给A添加来源标记(最推荐,耦合低)

在视图控制器A里定义一个枚举,用来标记跳转来源:

enum ViewControllerSource {
    case B
    case C
    case D
}

class ViewControllerA: UIViewController {
    var source: ViewControllerSource?
    // ... 其他代码
}

然后在跳转的地方给这个属性赋值:

  • B模态跳转时:
let aVC = storyboard?.instantiateViewController(withIdentifier: "ViewControllerA") as! ViewControllerA
aVC.source = .B
present(aVC, animated: true)
  • C或D push跳转时:
let aVC = storyboard?.instantiateViewController(withIdentifier: "ViewControllerA") as! ViewControllerA
aVC.source = .C // D的话就设为.D
navigationController?.pushViewController(aVC, animated: true)

最后在A的返回逻辑里判断:

@IBAction func backButtonTapped(_ sender: UIButton) {
    guard let source = source else { return }
    switch source {
    case .B:
        dismiss(animated: true)
    case .C, .D:
        navigationController?.popViewController(animated: true)
    }
}

这个方法逻辑清晰,后续如果新增跳转来源,直接扩展枚举就行,完全不影响现有代码。

方案2:通过导航控制器和呈现控制器判断(适合不需要区分C/D的场景)

如果你的需求只是回退,不需要区分是从C还是D过来的,那可以直接通过两个属性判断:

@IBAction func backButtonTapped(_ sender: UIButton) {
    // 存在presentingViewController,说明是模态跳转(来自B)
    if presentingViewController != nil {
        dismiss(animated: true)
    } 
    // 存在navigationController,说明是push跳转(来自C或D)
    else if navigationController != nil {
        navigationController?.popViewController(animated: true)
    }
}

这个方法不用额外加属性,代码更简洁,但缺点是没法区分C和D,如果后续需要针对C/D做不同逻辑,就不太方便了。

方案3:通过导航栈的前一个控制器判断(耦合较高,不推荐长期使用)

如果不想加标记,也可以直接从导航栈里取前一个控制器来判断:

@IBAction func backButtonTapped(_ sender: UIButton) {
    if let presentingVC = presentingViewController {
        presentingVC.dismiss(animated: true)
    } else if let navController = navigationController, navController.viewControllers.count > 1 {
        let previousVC = navController.viewControllers[navController.viewControllers.count - 2]
        if previousVC is ViewControllerC || previousVC is ViewControllerD {
            navController.popViewController(animated: true)
        }
    }
}

不过这个方法会让A和C、D产生耦合,后续如果C/D改名或者结构变化,这里的代码也要跟着改,维护成本较高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:29:11