iOS双Tab应用点击Home页TableView收藏后Saved页数据不累积问题求助
问题根因
你的猜测正确,核心问题是每次给cell设置saveButtonDelegate时,都重新创建了SavedViewController的新实例,而非使用TabBar中已经存在的同一个SavedViewController实例。每个新实例的countryDataArray都是空的初始状态,所以每次追加数据都只会往新实例的数组存储当前点击的国家,无法实现数据累积。
除此之外你当前的逻辑还存在两个隐藏问题:
- 仅实现了新增收藏逻辑,没有处理取消收藏场景
- cell复用场景下没有重置星标状态,会出现显示和实际收藏状态不一致的错乱问题
解决方法
方案1:全局收藏状态单独维护全局收藏数据(最推荐,耦合性低易扩展)
收藏数据属于全局状态,不应该绑定在某个ViewController实例上,建议单独封装一个全局收藏管理类维护统一的收藏数组,所有页面都访问同一份数据即可。
- 实现全局收藏管理类:
// 全局收藏管理类 class FavoritesManager { static let shared = FavoritesManager() private init() { // 可选:启动时读取本地持久化的收藏数据 if let data = UserDefaults.standard.data(forKey: "FavoriteCountries"), let list = try? JSONDecoder().decode([CountryData].self, from: data) { favoriteCountries = list } } // 全局统一的收藏数组 var favoriteCountries: [CountryData] = [] { didSet { // 可选:收藏变化时自动持久化到本地,App重启后数据不丢失 if let data = try? JSONEncoder().encode(favoriteCountries) { UserDefaults.standard.set(data, forKey: "FavoriteCountries") } } } // 切换收藏状态 func toggleFavorite(country: CountryData) { if let index = favoriteCountries.firstIndex(where: { $0.name == country.name }) { favoriteCountries.remove(at: index) } else { favoriteCountries.append(country) } } // 判断当前国家是否已收藏 func isFavorited(country: CountryData) -> Bool { return favoriteCountries.contains(where: { $0.name == country.name }) } }
- 修改cell按钮点击逻辑,不再代理给
SavedViewController,直接调用全局管理类:
@objc func buttonTapped() { let currentIsFavorited = FavoritesManager.shared.isFavorited(country: countryData) // 切换收藏状态 FavoritesManager.shared.toggleFavorite(country: countryData) // 更新按钮UI let image = currentIsFavorited ? UIImage(systemName: "star") : UIImage(systemName: "star.fill") saveButton.setImage(image, for: .normal) isSaveButtonSelected = !currentIsFavorited // 发送通知通知收藏列表页刷新 NotificationCenter.default.post(name: NSNotification.Name("FavoritesUpdated"), object: nil) }
- 在
SavedViewController监听通知刷新列表,同时每次页面展示时同步最新数据:
class SavedViewController: UIViewController { var countryDataArray: [CountryData] = [] override func viewDidLoad() { super.viewDidLoad() // 监听收藏变化通知 NotificationCenter.default.addObserver(self, selector: #selector(refreshFavoritesList), name: NSNotification.Name("FavoritesUpdated"), object: nil) } // 每次切换到Saved页时同步最新收藏数据 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) refreshFavoritesList() } @objc private func refreshFavoritesList() { countryDataArray = FavoritesManager.shared.favoriteCountries DispatchQueue.main.async { self.countriesTableView.reloadData() } } }
- 在Home页的
cellForRowAt方法中补充cell复用的星标状态赋值,避免复用错乱:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CountriesTableViewCell", for: indexPath) as! CountriesTableViewCell let currentCountry = 你的首页数据源[indexPath.row] cell.countryData = currentCountry // 根据实际收藏状态设置按钮UI let isFavorited = FavoritesManager.shared.isFavorited(country: currentCountry) cell.isSaveButtonSelected = isFavorited cell.saveButton.setImage(isFavorited ? UIImage(systemName: "star.fill") : UIImage(systemName: "star"), for: .normal) return cell }
方案2:复用TabBar中已存在的SavedViewController实例(不推荐,耦合性高)
如果不想调整现有代理架构,可以在Home页给cell设置delegate时,从TabBar的已加载的控制器数组中找到已经初始化完成的SavedViewController实例,保证所有cell的代理指向同一个实例即可:
// Home页的cellForRowAt方法中 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CountriesTableViewCell", for: indexPath) as! CountriesTableViewCell let currentCountry = 你的首页数据源[indexPath.row] cell.countryData = currentCountry // 找到TabBar中已经存在的SavedViewController实例 if let savedVC = self.tabBarController?.viewControllers?.first(where: { $0 is SavedViewController }) as? SavedViewController { cell.saveButtonDelegate = savedVC // 同步星标状态避免复用错乱 let isFavorited = savedVC.countryDataArray.contains(where: { $0.name == currentCountry.name }) cell.isSaveButtonSelected = isFavorited cell.saveButton.setImage(isFavorited ? UIImage(systemName: "star.fill") : UIImage(systemName: "star"), for: .normal) } return cell }
内容的提问来源于stack exchange,提问作者balbi
相关产品推荐
相关产品推荐

