点击Tab Bar时如何修改Navigation Item内容及对应按钮?
成熟实现方案
核心逻辑很简单:不要把导航栏按钮的配置、交互逻辑全堆在UITabBarControllerDelegate里,把对应逻辑下沉到每个子页面的ViewController自行管理,是UIKit原生支持、维护成本最低的做法。
方案1:子控制器自主配置(优先推荐)
你现在遇到两个页面Navigation Item默认一致,本质是把导航项配置写在了TabBarController或者外层公共NavigationController里,实际上UIKit的导航栏会自动读取当前导航栈栈顶ViewController的navigationItem属性做展示,完全不需要你手动在tab切换时替换图标。
直接在两个Scene对应的独立ViewController里,各自在viewDidLoad生命周期配置专属的右侧按钮、绑定对应交互即可,代码完全隔离,不会串逻辑:
// 第一个Scene对应的ViewController override func viewDidLoad() { super.viewDidLoad() // 配置第一个页面专属的右侧按钮 let rightBtn = UIBarButtonItem( barButtonSystemItem: .add, target: self, action: #selector(firstPageRightBtnAction) ) navigationItem.rightBarButtonItem = rightBtn } @objc private func firstPageRightBtnAction() { // 写第一个页面独有的按钮点击逻辑,比如跳转新增页 }
// 第二个Scene对应的ViewController override func viewDidLoad() { super.viewDidLoad() // 配置第二个页面专属的右侧按钮 let rightBtn = UIBarButtonItem( title: "编辑", style: .plain, target: self, action: #selector(secondPageRightBtnAction) ) navigationItem.rightBarButtonItem = rightBtn } @objc private func secondPageRightBtnAction() { // 写第二个页面独有的按钮点击逻辑,比如进入编辑模式 }
这个写法没有任何耦合,后续要改哪个页面的按钮样式、交互,直接去对应ViewController里改就行,不会因为tab切换的判断逻辑写错导致按钮串页、触发错事件。
方案2:沿用现有TabBarControllerDelegate逻辑补全交互
如果你已经写了不少delegate里切换按钮图标的代码,不想重构现有逻辑,也可以在tab切换的代理方法里,给按钮绑定对应子控制器的事件,注意不要把所有事件逻辑都写在TabBarController里,避免后续代码臃肿:
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { // 拿到当前选中页面所在导航栈的栈顶控制器 guard let navVC = tabBarController.selectedViewController as? UINavigationController, let topVC = navVC.topViewController else { return } // 根据当前选中的页面配置不同按钮和交互 if topVC is FirstSceneViewController { let btn = UIBarButtonItem( image: UIImage(named: "first_page_btn_icon"), style: .plain, target: topVC, action: #selector(FirstSceneViewController.firstPageRightBtnAction) ) topVC.navigationItem.rightBarButtonItem = btn } else if topVC is SecondSceneViewController { let btn = UIBarButtonItem( image: UIImage(named: "second_page_btn_icon"), style: .plain, target: topVC, action: #selector(SecondSceneViewController.secondPageRightBtnAction) ) topVC.navigationItem.rightBarButtonItem = btn } }
避坑提示
- 不要复用同一个UIBarButtonItem实例给两个页面用,会出现target/action被覆盖、按钮状态错乱的问题,每个页面对应独立的按钮实例即可。
- 如果后续页面有滚动时调整导航栏透明度、隐藏导航栏之类的需求,子控制器自主配置的方案不会出现状态冲突,比在TabBar层统一管理稳定性高很多。
内容的提问来源于stack exchange,提问作者Emdetto
相关产品推荐
相关产品推荐

