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

Swift Tab Bar徽章实现:点击Cell按钮后在第二个TabBarItem显示数组计数

解决TabBarItem徽章随UserDefaults数组更新的问题

我来帮你梳理下问题,你之前用协议的思路其实是对的,大概率是代理没正确绑定或者后续更新TabBar的步骤没到位。下面给你一套完整的可落地方案:

第一步:完善CollectionViewCell的协议与按钮点击逻辑

先在你的Cell类里定义协议,用来通知主VC按钮被点击了,同时传递Label的文本:

import UIKit

protocol CollectionViewCellDelegate: AnyObject {
    func didTapSaveButton(withText text: String)
}

class YourCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var saveButton: UIButton!
    @IBOutlet weak var contentLabel: UILabel!
    
    weak var delegate: CollectionViewCellDelegate?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        saveButton.addTarget(self, action: #selector(saveButtonTapped), for: .touchUpInside)
    }
    
    @objc private func saveButtonTapped() {
        guard let text = contentLabel.text, !text.isEmpty else { return }
        delegate?.didTapSaveButton(withText: text)
    }
}

第二步:主VC实现代理,更新UserDefaults并同步TabBar徽章

在带CollectionView的主VC里,实现代理方法,同时处理数组的存储和徽章更新:

class MainCollectionVC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, CollectionViewCellDelegate {
    
    // 定义UserDefaults的key,方便复用
    private let savedTextsKey = "SavedTextsArray"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 应用启动时先初始化徽章
        updateTabBarBadge()
        // 绑定CollectionView的数据源与代理
        collectionView.dataSource = self
        collectionView.delegate = self
    }
    
    // CollectionView的cell初始化方法里绑定代理
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCellID", for: indexPath) as! YourCollectionViewCell
        // 给cell的Label赋值你的业务数据
        cell.contentLabel.text = "示例文本\(indexPath.item)"
        // 关键:绑定代理到当前VC
        cell.delegate = self
        return cell
    }
    
    // 实现代理方法,处理按钮点击后的逻辑
    func didTapSaveButton(withText text: String) {
        // 从UserDefaults读取已有数组,没有则初始化空数组
        var savedTexts = UserDefaults.standard.array(forKey: savedTextsKey) as? [String] ?? []
        // 可选:避免重复添加同一文本
        if !savedTexts.contains(text) {
            savedTexts.append(text)
            // 将更新后的数组存回UserDefaults
            UserDefaults.standard.set(savedTexts, forKey: savedTextsKey)
            // 更新TabBar徽章
            updateTabBarBadge()
        }
    }
    
    // 封装徽章更新方法,方便复用
    private func updateTabBarBadge() {
        let count = UserDefaults.standard.array(forKey: savedTextsKey)?.count ?? 0
        // 获取TabBarController的第二个TabBarItem
        if let tabBarItems = self.tabBarController?.tabBar.items, tabBarItems.count >= 2 {
            // 数量为0时隐藏徽章,否则显示数字
            tabBarItems[1].badgeValue = count > 0 ? "\(count)" : nil
        }
    }
}

第三步:常见问题排查

如果你之前用协议没成功,大概率是这几个原因:

  • 没有在cellForItemAt方法里给cell的delegate赋值为self
  • 更新徽章时没有正确获取TabBarItem(比如主VC嵌套在NavigationController里,需要先获取NavigationController的父控制器)
  • UserDefaults的数组读写逻辑有误

如果主VC是嵌套在NavigationController中的,修改updateTabBarBadge方法的TabBarController获取逻辑:

private func updateTabBarBadge() {
    let count = UserDefaults.standard.array(forKey: savedTextsKey)?.count ?? 0
    // 先拿到NavigationController的父控制器(即TabBarController)
    if let tabBarController = self.navigationController?.parent as? UITabBarController,
       let tabBarItems = tabBarController.tabBar.items, tabBarItems.count >= 2 {
        tabBarItems[1].badgeValue = count > 0 ? "\(count)" : nil
    }
}

这套流程下来,点击Cell按钮后文本会被加入UserDefaults数组,第二个TabBarItem的徽章会实时更新数字,应用启动时也会根据已存储的数组设置初始徽章。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:22:21