Swift 如何基于API返回的省份数据实现Collection View动态行数控制?
原实现的核心错误点
- 计数逻辑完全偏离目标:手动循环遍历1...100的硬编码范围,既没有处理数组边界(实际数组长度小于100时会直接触发越界崩溃),也没有逐次累加匹配到的条目数,只要遇到第一个符合省份条件的元素,就直接把count赋值为整个summary数组的总长度,完全不是符合条件的条目总数。
- 单元格渲染数据错位:没有对原始数据做提前过滤,直接拿Collection View的indexPath去原始summary数组取数据,一旦indexPath对应的位置是其他省份的数据,就会出现取空值、数据和单元格不匹配的问题。
- 缺少返回分支兜底:在cellForItemAt方法里做省份匹配判断后,没有else分支的cell返回逻辑,一旦判断不通过就没有可返回的单元格,会触发运行时崩溃。
正确实现方案
最稳妥的做法是提前完成数据过滤,把符合选中省份条件的单独存为一个数据源数组,所有Collection View的渲染逻辑都基于这个过滤后的数组实现,不要在数据源方法里临时做判断。
- 新增一个存储过滤结果的属性
// 存储当前选中省份下的所有卫生区域数据 private var filteredRegionList: [SummaryItem] = [] - 选中省份触发页面切换时,先执行数据过滤,再刷新视图
// 完成省份选择、拿到dataFromSelection后执行 guard let fullSummaryData = jsonData?.summary else { return } filteredRegionList = fullSummaryData.filter { $0.province == dataFromSelection } // 数据更新后刷新Collection View myCollectionView.reloadData() - 重写Collection View数据源方法
- 计数方法直接返回过滤后的数组长度,不需要手动循环:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return filteredRegionList.count } - 单元格渲染直接从过滤后的数组取对应下标的数据,不需要在方法里重复做省份判断:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard collectionView == myCollectionView else { // 其他关联的Collection View逻辑在此补充 return UICollectionViewCell() } let regionData = filteredRegionList[indexPath.row] let todayCases = regionData.cases let totalDeaths = regionData.cumulative_deaths let totalCases = regionData.cumulative_cases let regionName = regionData.health_region let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RegionCell", for: indexPath) as! RegionCell cell.configure(region: regionName, totCase: totalCases, todCases: todayCases, totDeaths: totalDeaths) return cell }
- 计数方法直接返回过滤后的数组长度,不需要手动循环:
方案优势
- 彻底避免数组越界:所有取数都基于过滤后的、长度完全匹配的数组,不存在下标超限问题
- 逻辑更简洁:不需要在多个数据源方法里重复写省份匹配判断,减少冗余代码
- 崩溃概率更低:过滤完成后取出的数据一定和选中省份匹配,不需要大量强制解包
内容的提问来源于stack exchange,提问作者Dungeon Master
相关产品推荐
相关产品推荐

