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

如何判断ViewControllerA是通过返回还是作为导航栈根控制器进入?

判断回到ViewControllerA的方式:是返回操作还是本身为根控制器

我之前做项目时也遇到过一模一样的需求,这里分享几个实用的解决方案,你可以根据自己的场景选最合适的:

方法一:利用导航控制器的代理(最靠谱,覆盖所有返回场景)

这个方法能捕捉到所有返回操作,包括系统默认的返回按钮、边缘侧滑返回,非常全面。

首先让你的ViewControllerA(或者专门的代理类)遵守UINavigationControllerDelegate协议,然后实现下面的代理方法:

func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
    // 先判断当前显示的是不是ViewControllerA
    guard let currentVC = viewController as? ViewControllerA else { return }
    
    // 通过transitionCoordinator获取跳转前的控制器
    if let previousVC = navigationController.transitionCoordinator?.viewController(forKey: .from) {
        if previousVC is ViewControllerB {
            // 确认是从ViewControllerB返回回到A的
            print("✅ 从ViewControllerB返回至A")
            // 这里可以写你需要的逻辑,比如刷新数据、弹提示等
        } else {
            // 不是从B返回的,可能是其他场景
            print("⚠️ 非B返回的方式进入A")
        }
    } else {
        // 没有跳转前的控制器,说明A是导航栈的根控制器,首次加载
        print("🏠 A是导航栈根控制器,首次显示")
    }
}

别忘了在合适的地方设置代理,比如ViewControllerA的viewDidLoad里:

override func viewDidLoad() {
    super.viewDidLoad()
    navigationController?.delegate = self
}

方法二:在ViewControllerA的viewWillAppear里判断(简单直接)

如果场景比较简单,也可以直接在A的viewWillAppear方法里结合导航栈的状态判断:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    guard let navVC = navigationController else { return }
    
    // 先判断A是不是根控制器
    let isRoot = navVC.viewControllers.first == self && navVC.viewControllers.count == 1
    
    if isRoot {
        // 首次以根控制器身份显示
        print("🏠 A是导航栈根控制器")
    } else {
        // 导航栈里还有其他控制器,说明是从某个页面返回的
        // 可以进一步判断返回来源是不是B
        if let previousVC = navVC.viewControllers[navVC.viewControllers.count - 2] as? ViewControllerB {
            print("✅ 从ViewControllerB返回至A")
        }
    }
}

不过这个方法有个小局限:如果是从C返回B,再从B返回A,当回到A时导航栈里只有A了,这时候navVC.viewControllers.count是1,就会误判成根控制器首次显示。所以更推荐第一种代理方法。

方法三:自定义返回按钮传递标记(适合需要控制返回行为的场景)

如果你需要自定义返回按钮的样式或逻辑,可以在B里给A设置一个标记,用来区分是否是返回操作:

首先在ViewControllerA里加一个标记变量:

var isBackFromB = false

然后在ViewControllerB里自定义返回按钮,并在点击时设置标记:

override func viewDidLoad() {
    super.viewDidLoad()
    // 替换系统返回按钮
    let customBackBtn = UIBarButtonItem(title: "返回", style: .plain, target: self, action: #selector(backToA))
    navigationItem.leftBarButtonItem = customBackBtn
}

@objc func backToA() {
    // 找到栈里的A控制器,设置标记
    if let aVC = navigationController?.viewControllers.first as? ViewControllerA {
        aVC.isBackFromB = true
    }
    navigationController?.popViewController(animated: true)
}

最后在ViewControllerA的viewWillAppear里判断标记:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    if isBackFromB {
        print("✅ 从ViewControllerB返回至A")
        isBackFromB = false // 用完记得重置,避免下次误判
    } else {
        print("🏠 A是根控制器或非B返回的场景")
    }
}

注意:这个方法无法覆盖系统的边缘侧滑返回,因为侧滑不会触发自定义的返回按钮事件,所以如果你的App支持侧滑返回,还是优先用第一种代理方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:41:02