如何修复UICollectionView中didSelectItemAt方法选中任意条目均仅显示首个足球联赛详情的问题?
问题分析与修复方案
我帮你排查下问题根源:你的代码里有两个核心问题导致了点击任意条目都跳转首个联赛的情况:
数据加载逻辑错误:在
fetchData方法中,你遍历Firestore文档时每次循环都调用了configureModels(leagues: [leaguess]),这会导致sections数组被重复添加多个leagueList类型的section——每个section里只有一个联赛条目。此时用户点击的每个item其实属于不同的section,indexPath.row始终是0,你用leagues[indexPath.row]自然只会取到第一个联赛。选中逻辑未与展示数据绑定:
didSelectItemAt直接依赖leagues数组和indexPath.row的映射,没有和当前展示的sections数据关联,一旦数据结构变化(比如多section场景)就会出错。
具体修复步骤
1. 修复数据加载逻辑(fetchData和configureModels)
先批量转换所有Firestore文档为LeaguesInfo数组,再一次性配置模型,避免重复创建section:
private func fetchData() { db.collection("leagues").addSnapshotListener { (snapshot, error) in DispatchQueue.main.async { guard let documents = snapshot?.documents else { print("No league data") return } // 批量转换所有文档为LeaguesInfo数组 let fetchedLeagues = documents.compactMap { documentSnapshot -> LeaguesInfo? in let data = documentSnapshot.data() let id = data["id"] as? String ?? "" let name = data["name"] as? String ?? "" let logo = data["logo"] as? String ?? "" return LeaguesInfo(id: id, name: name, logo: logo) } // 一次性配置模型,避免逐个添加section self.configureModels(leagues: fetchedLeagues) } } } private func configureModels(leagues: [LeaguesInfo]) { self.leagues = leagues // 先清空sections,避免数据更新时重复添加section sections.removeAll() // 仅创建一个section,包含所有联赛的viewModel sections.append(.leagueList(viewModels: leagues.compactMap({ return LeagueCellViewModel(id: $0.id, name: $0.name, logo: URL(string: $0.logo)) }))) collectionView.reloadData() }
2. 修复选中逻辑(didSelectItemAt)
从当前展示的sections数据中获取选中的条目,保证点击内容与跳转内容完全同步:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { collectionView.deselectItem(at: indexPath, animated: true) let type = sections[indexPath.section] switch type { case .leagueList(let viewModels): // 获取当前选中的viewModel let selectedViewModel = viewModels[indexPath.row] // 通过id匹配对应的联赛(比直接用index更健壮,适配后续可能的排序/过滤场景) if let selectedLeague = leagues.first(where: { $0.id == selectedViewModel.id }) { let vc = LeagueViewController(league: selectedLeague) vc.title = selectedLeague.name vc.navigationItem.largeTitleDisplayMode = .never navigationController?.pushViewController(vc, animated: true) } } }
修复说明
- 修复后,所有联赛条目会被放在同一个section中,
indexPath.row会正确对应每个条目的位置(0、1、2...)。 - 选中逻辑通过
sections数据关联,保证了点击的条目和跳转的详情页完全匹配,即使后续数据结构变化(比如新增其他类型的section)也不会出错。
内容的提问来源于stack exchange,提问作者Garmani
相关产品推荐
相关产品推荐

