自定义UITableViewCell选中显示勾选图,优化reloadData低效问题
优化UITableView单选勾选图标的实现方案
你的当前实现通过全量刷新列表来更新勾选状态,确实会在数据量大时影响性能。下面是两种更高效的优化方案,优先推荐第一种:
方案一:仅刷新必要的单元格(推荐)
通过reloadRows(at:with:)只刷新之前选中的单元格和当前选中的单元格,避免全量刷新整个列表。
修改GoalsTableVC中的didSelectRowAt方法:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // 记录之前选中的单元格索引 let previousIndexPath = IndexPath(row: selectedInd, section: 0) // 更新当前选中的目标ID和索引 selectedGoalId = goalsData[indexPath.row].id! selectedInd = indexPath.row // 仅刷新两个需要变更状态的单元格 tableView.reloadRows(at: [previousIndexPath, indexPath], with: .automatic) }
同时可以简化cellForRowAt里的判断逻辑,让代码更简洁:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let gCell = tableView.dequeueReusableCell(withIdentifier: "gCell", for: indexPath) as! GoalsTableViewCell gCell.gNameLabel.text = goalsData[indexPath.row].gName // 直接通过判断设置勾选图标的隐藏状态 gCell.gIsSelectedImage.isHidden = (indexPath.row != selectedInd) return gCell }
这种方法的优势:
- 只更新需要变更的单元格,性能远优于全量刷新
- 无论单元格是否在屏幕可见范围内,都能保证状态正确(因为单元格复用时
cellForRowAt会重新设置状态)
方案二:直接修改可见单元格的UI状态
如果列表数据量很小,也可以直接获取屏幕上可见的单元格,修改它们的勾选图标状态,无需刷新单元格:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // 隐藏之前选中单元格的勾选图标 if let previousCell = tableView.cellForRow(at: IndexPath(row: selectedInd, section: 0)) as? GoalsTableViewCell { previousCell.gIsSelectedImage.isHidden = true } // 显示当前选中单元格的勾选图标 if let currentCell = tableView.cellForRow(at: indexPath) as? GoalsTableViewCell { currentCell.gIsSelectedImage.isHidden = false } // 更新选中状态记录 selectedGoalId = goalsData[indexPath.row].id! selectedInd = indexPath.row }
注意:这种方法仅适用于之前选中的单元格仍在屏幕可见范围内的情况,如果该单元格已滚出屏幕,tableView.cellForRow(at:)会返回nil,此时该单元格的状态会在它重新滚入屏幕时,通过cellForRowAt的逻辑自动修正,日常使用中也能满足需求,但方案一更稳妥。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

