如何在UITabBarController子控制器中更新导航标题并设置代理?
我来帮你解决这个问题,其实核心就是通过代理模式让子视图控制器把点击次数传递给UITabBarController,然后由后者来更新导航标题。下面是一步步的具体实现方案:
第一步:定义代理协议,在子VC中传递点击事件
首先在你的子视图控制器文件里,定义一个代理协议,用来传递点击次数:
// 子视图控制器文件 import UIKit // 定义代理协议 protocol ButtonTapCountDelegate: AnyObject { func didUpdateButtonTapCount(_ count: Int) } class YourChildViewController: UIViewController { // 声明弱引用的代理属性(避免循环引用) weak var delegate: ButtonTapCountDelegate? // 统计点击次数的变量 private var tapCount = 0 // 按钮点击事件 @IBAction func yourButtonTapped(_ sender: UIButton) { tapCount += 1 // 调用代理方法,把最新的点击次数传出去 delegate?.didUpdateButtonTapCount(tapCount) } }
第二步:让UITabBarController遵守代理协议并实现方法
接下来在你的UITabBarController类里,遵守刚才定义的代理协议,并且实现更新导航标题的逻辑:
// UITabBarController文件 import UIKit class YourTabBarController: UITabBarController, ButtonTapCountDelegate { override func viewDidLoad() { super.viewDidLoad() // 设置子VC的代理为当前UITabBarController setupChildVCDelegate() } // 实现代理方法,更新导航标题 func didUpdateButtonTapCount(_ count: Int) { // 如果是更新UITabBarController自身的导航标题(当它被包裹在UINavigationController里时) navigationItem.title = "点击次数:\(count)" // 如果你想更新当前活跃子VC的导航标题,可以用下面这段代码 // if let currentNav = selectedViewController as? UINavigationController, // let currentVC = currentNav.topViewController { // currentVC.navigationItem.title = "点击次数:\(count)" // } } // 设置子VC的代理 private func setupChildVCDelegate() { // 遍历UITabBarController的所有子控制器 for child in viewControllers ?? [] { // 情况1:子VC被包裹在UINavigationController里(常见场景) if let navVC = child as? UINavigationController, let targetChildVC = navVC.rootViewController as? YourChildViewController { targetChildVC.delegate = self break // 找到目标VC后就停止遍历,如果你有多个子VC需要设置,就去掉break } // 情况2:子VC没有被导航控制器包裹 // if let targetChildVC = child as? YourChildViewController { // targetChildVC.delegate = self // break // } } } }
关键注意点:为什么要用weak修饰代理?
如果不用weak修饰代理属性,子VC的代理会持有UITabBarController,而UITabBarController又持有子VC,会形成循环引用,导致两个控制器都无法被系统释放,造成内存泄漏。
替代方案:用通知中心传递数据
如果你觉得代理模式有点繁琐,也可以用NotificationCenter来实现:
- 在子VC的按钮点击事件里发送通知:
@IBAction func yourButtonTapped(_ sender: UIButton) { tapCount += 1 NotificationCenter.default.post( name: NSNotification.Name("ButtonTapCountUpdated"), object: tapCount ) }
- 在UITabBarController里监听通知并更新标题:
override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(updateTitleWithNotification(_:)), name: NSNotification.Name("ButtonTapCountUpdated"), object: nil ) } @objc private func updateTitleWithNotification(_ notification: Notification) { guard let count = notification.object as? Int else { return } navigationItem.title = "点击次数:\(count)" } // 记得在销毁时移除监听,避免野指针 deinit { NotificationCenter.default.removeObserver(self) }
不过更推荐用代理模式,因为它是一对一的精准传递,而通知是广播式的,更适合需要多个对象接收消息的场景。
内容的提问来源于stack exchange,提问作者Cody Harness
相关产品推荐
相关产品推荐

