Swift 4 UITableView多行复选框添加/移除及滚动复用异常问题求助
解决Swift 4 UITableView滚动后复用Cell状态异常的问题
嘿,这个问题我太熟了——本质是UITableView的Cell复用机制在搞鬼!你现在的写法只修改了当前显示Cell的UI状态,却没有把选中状态和数据源绑定,滚动时复用旧Cell就会把之前的勾选状态带过来,而高亮状态是由TableView管理的,所以新出现的Cell只会保留勾选,不会自动高亮。
下面是具体的修复方案:
1. 维护一个记录选中状态的数据源
首先在你的ViewController里添加一个集合,用来保存所有被选中的IndexPath:
// 用Set来存储,方便快速添加/删除和判断是否存在 var selectedIndexPaths: Set<IndexPath> = []
2. 修改选中/取消选中的逻辑,同步数据源和UI
更新didSelectRowAt和didDeselectRowAt方法,确保每次操作都先更新数据源,再同步Cell的UI:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // 先更新数据源 if selectedIndexPaths.contains(indexPath) { selectedIndexPaths.remove(indexPath) tableView.deselectRow(at: indexPath, animated: true) } else { selectedIndexPaths.insert(indexPath) } // 同步当前Cell的勾选状态 if let cell = tableView.cellForRow(at: indexPath) { cell.accessoryType = selectedIndexPaths.contains(indexPath) ? .checkmark : .none } } func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { // 从数据源移除 selectedIndexPaths.remove(indexPath) // 取消当前Cell的勾选 if let cell = tableView.cellForRow(at: indexPath) { cell.accessoryType = .none } }
3. 在Cell复用的时候,根据数据源重置状态
这是最关键的一步!在cellForRowAt方法里,必须根据我们维护的数据源来设置Cell的勾选和选中状态,确保复用的Cell能正确显示:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "你的Cell标识符", for: indexPath) // 这里设置你的Cell内容,比如textLabel的文字等 // 根据数据源设置勾选状态 cell.accessoryType = selectedIndexPaths.contains(indexPath) ? .checkmark : .none // 根据TableView的选中记录设置高亮/选中状态 let isSelected = tableView.indexPathsForSelectedRows?.contains(indexPath) ?? false cell.isSelected = isSelected cell.isHighlighted = isSelected return cell }
为什么之前的写法会出问题?
UITableView为了性能,只会创建屏幕可见数量的Cell,当你滚动时,滑出屏幕的Cell会被回收复用给新进入屏幕的行。你之前直接修改Cell的accessoryType但没记录到数据源里,复用的时候旧Cell的勾选状态就会被带到新行上;而高亮状态是由TableView统一管理的,新复用的Cell不会自动继承高亮,所以就出现了“被勾选但未高亮”的情况。
内容的提问来源于stack exchange,提问作者winstonj
相关产品推荐
相关产品推荐

