UITabBarController按条件切换第二标签视图控制器及标签栏不显示问题求解
问题原因
你现有两个实现方案的问题分别如下:
- 直接修改
window.rootViewController:你直接将应用根控制器从原来的UITabBarController替换为了业务VC,整个标签栏控制器被移除,自然不会显示底部tabBar。 - 调用
self.navigationController?.push出现空白:如果你的UITabBarController本身没有被UINavigationController嵌套,它的navigationController属性为nil,push逻辑不会执行,点击后只会加载你提前绑定到第二个标签的默认VC,如果没有绑定默认VC就会出现空白。
正确实现方案
需求核心是点击第二个标签时保留底部tabBar,只切换该标签对应的显示内容,推荐以下两种实现方式:
方案1:动态替换标签对应的视图控制器
直接修改UITabBarController的viewControllers数组中第二个标签对应的VC,适合不需要该标签下多页面导航的场景:
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { // 确认点击的是第二个标签,根据你实际的tag或索引调整判断条件 guard item.tag == 2, let index = tabBar.items?.firstIndex(of: item) else { return } // 根据条件生成目标VC let targetVC: UIViewController if UserDefaults.standard.bool(forKey: "FirstTimeUser") { targetVC = storyboard!.instantiateViewController(withIdentifier: "CreateNewProjectViewController") as! CreateNewProjectViewController } else { targetVC = storyboard!.instantiateViewController(withIdentifier: "ProjectsViewController") as! ProjectsViewController } // 如果需要该标签支持导航跳转,给目标VC套一层导航控制器 let targetNav = UINavigationController(rootViewController: targetVC) // 替换标签对应VC var vcList = self.viewControllers ?? [] vcList[index] = targetNav self.viewControllers = vcList // 手动选中对应标签确保内容正常显示 self.selectedIndex = index }
方案2:提前给第二个标签绑定导航控制器,切换导航栈根VC
如果需要该标签支持多页面push跳转,可以提前在Storyboard中给第二个标签绑定一个空的UINavigationController,点击时直接修改导航栈的根VC即可:
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { guard item.tag == 2 else { return } // 拿到第二个标签提前绑定的导航控制器 guard let targetNav = self.viewControllers?[1] as? UINavigationController else { return } // 生成目标VC let targetVC: UIViewController if UserDefaults.standard.bool(forKey: "FirstTimeUser") { targetVC = storyboard!.instantiateViewController(withIdentifier: "CreateNewProjectViewController") as! CreateNewProjectViewController } else { targetVC = storyboard!.instantiateViewController(withIdentifier: "ProjectsViewController") as! ProjectsViewController } // 替换导航栈根VC,需要切换动画可以改为pushViewController targetNav.setViewControllers([targetVC], animated: false) }
注意事项
- 确保Storyboard中业务VC的
Storyboard ID和代码中填写的完全一致,避免运行时崩溃 - 不要将整个
UITabBarController嵌套在UINavigationController中,建议给每个标签对应的VC单独嵌套导航控制器,避免push时tabBar被隐藏 - 如果需要切换页面时保留用户之前的操作状态,可以提前缓存两个业务VC的实例,不需要每次点击都重新创建
内容的提问来源于stack exchange,提问作者iosDevSan
相关产品推荐
相关产品推荐

