求助:TabViewController中NavigationController无法返回不同Storyboard的上一级ViewController
首先得明确核心问题:你调用_ = navigationController?.popViewController(animated: true)没效果,大概率是因为你当前拿到的navigationController并不是包含你要返回的上一级页面的那个导航栈。先给你拆解几种常见场景和对应的解决方法:
1. 先排查导航栈结构(关键第一步)
在执行pop前,先打印当前导航栈的视图控制器列表,确认目标页面是否在栈里:
print(navigationController?.viewControllers ?? [])
如果输出里没有你要返回的那个页面,那pop自然无效,这时候要先理清你的页面跳转方式是push还是present。
2. 场景一:上一级页面是通过push进入当前导航栈的
假设你的层级是这样的:VC1(来自Storyboard A) → push → 外层UINavigationController(root是UITabBarController) → TabBar内部每个Tab又嵌套了自己的NavigationController(比如Tab1对应NavTab1,其root是VC2来自Storyboard B)
这时候你在VC2里直接调用navigationController?.popViewController,操作的是Tab内部的NavTab1的栈(而这个栈里只有VC2),当然没用。你需要拿到外层的那个导航控制器来执行pop:
// 先拿到TabBar控制器,再获取它所属的外层导航栈 if let tabBarVC = self.tabBarController, let outerNav = tabBarVC.navigationController { outerNav.popViewController(animated: true) }
3. 场景二:上一级页面是通过present方式展示当前Tab相关页面的
如果当初是从VC1 present了TabBarController(或者包含TabBar的导航控制器),那popViewController完全不适用——present出来的页面需要用dismiss返回:
self.dismiss(animated: true, completion: nil)
这种混淆push和present返回方式的情况很常见,你可以回忆下当初跳转时用的是performSegue(如果是push类型的segue)还是直接调用present(_:animated:)方法。
4. 场景三:跨Storyboard初始化TabBar导致的导航栈问题
如果你是在VC1里从另一个Storyboard初始化TabBarController并push的,比如:
let tabStoryboard = UIStoryboard(name: "TabBarStoryboard", bundle: nil) let tabBarVC = tabStoryboard.instantiateInitialViewController() as! UITabBarController navigationController?.pushViewController(tabBarVC, animated: true)
这时候导航栈是VC1 → TabBarVC,你在TabBar的子VC里需要先拿到TabBarVC,再获取它的导航控制器来pop:
if let nav = self.tabBarController?.navigationController { nav.popViewController(animated: true) }
额外小技巧
可以用Xcode的Debug View Hierarchy功能查看当前视图控制器的层级结构,能直观看到每个VC的父控制器、所属导航栈关系,快速定位问题。
内容的提问来源于stack exchange,提问作者Pyae Phyoe Shein

