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

Swift中隐藏tabBar时如何同步隐藏通知红点?

嘿,这个问题我之前帮好几个开发者捋清楚过,核心就是把tabBar的显示状态和小红点(badge)的显示状态绑定起来就行,下面给你两种实用的方案,你可以根据自己的项目架构来选:

方案一:自定义UITabBarController(最推荐,逻辑集中好维护)

这种方式把所有和tabBar、badge相关的逻辑都收拢在子类里,后期改需求也方便:

  1. 先给UITabBarController做个自定义子类,比如叫CustomTabBarController
  2. 在子类里写一个统一管理badge显示/隐藏的方法,这里要注意保存原来的badge值,不然隐藏后再回来就丢了:
func updateBadgeVisibility() {
    guard let tabBarItems = tabBar.items else { return }
    // 判断当前tabBar是否需要显示(这里可以根据tabBar.isHidden,或者你自己维护的状态)
    let shouldShowBadges = !tabBar.isHidden
    
    for item in tabBarItems {
        let badgeKey = "SavedBadge_\(item.tag)"
        if shouldShowBadges {
            // 恢复之前保存的badge值
            item.badgeValue = UserDefaults.standard.string(forKey: badgeKey) ?? item.badgeValue
        } else {
            // 先保存当前badge值,再清空显示
            UserDefaults.standard.set(item.badgeValue, forKey: badgeKey)
            item.badgeValue = nil
        }
    }
}

提示:如果你的badge值是从服务器接口或本地数据库实时获取的,也可以直接从数据源拉取恢复,不用存在UserDefaults里,这样更准确。

  1. 监听tabBar的显示状态变化,比如你常用hidesBottomBarWhenPushed = true来隐藏tabBar的话,让自定义的tabBarController充当导航控制器的代理,在导航栈变化时自动更新badge:
extension CustomTabBarController: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        // 这里会自动处理push/pop时的tabBar显示状态
        DispatchQueue.main.async {
            self.updateBadgeVisibility()
        }
    }
}

别忘了在viewDidLoad里设置代理:

override func viewDidLoad() {
    super.viewDidLoad()
    navigationController?.delegate = self
}
方案二:通知+全局状态(适合不想改tabBarController的情况)

如果你的项目已经用了系统的UITabBarController,不想改子类,可以用通知来触发badge的显示/隐藏:

  1. 先定义一个通知名称:
extension Notification.Name {
    static let tabBarVisibilityChanged = Notification.Name("TabBarVisibilityChanged")
}
  1. 在tabBar所在的控制器(比如每个tab的根VC,或者直接在UITabBarController的分类里)添加监听:
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(updateBadgeStatus), name: .tabBarVisibilityChanged, object: nil)
}

@objc private func updateBadgeStatus(_ notification: Notification) {
    guard let isTabBarHidden = notification.userInfo?["isHidden"] as? Bool,
          let tabBarItems = tabBar.items else { return }
    
    for item in tabBarItems {
        let saveKey = "TabBadge_\(item.tag)"
        if isTabBarHidden {
            UserDefaults.standard.set(item.badgeValue, forKey: saveKey)
            item.badgeValue = nil
        } else {
            item.badgeValue = UserDefaults.standard.string(forKey: saveKey)
        }
    }
}
  1. 当你要隐藏tabBar时(比如在push的VC的viewWillAppear里)发送通知:
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    hidesBottomBarWhenPushed = true
    NotificationCenter.default.post(name: .tabBarVisibilityChanged, object: nil, userInfo: ["isHidden": true])
}
  1. 当返回带tabBar的页面时(比如在tab根VC的viewWillAppear里)发送恢复通知:
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.post(name: .tabBarVisibilityChanged, object: nil, userInfo: ["isHidden": false])
}
额外注意点
  • UITabBarItem的badgeValue是字符串类型,如果你的通知数是数字,记得转成字符串再设置
  • 如果是present弹窗隐藏tabBar的情况,在present前发送隐藏通知,dismiss后发送恢复通知就行
  • 记得在控制器销毁时移除通知监听(方案二需要):
deinit {
    NotificationCenter.default.removeObserver(self)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:31:17