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
相关产品推荐
相关产品推荐

