UITableView批量更新后哪些cell可见?移动行后如何正确配置cell?
UITableView 批量更新行移动处理逻辑解答
操作索引规则明确
首先纠正你之前的推测:performBatchUpdates 内四类操作的索引基准有明确的统一规则:
- 删除操作的索引:对应批量更新执行前的初始状态
- 插入、移动的目标索引(即
moveRow(at:to:)中的to参数):对应所有删除操作执行完成后的最终状态 - 移动的源索引(即
moveRow(at:to:)中的at参数):对应批量更新执行前的初始状态 - 刷新操作(
reloadRows)的索引:对应批量更新执行前的初始状态,如果你需要在移动后刷新行,建议放到完成块执行,避免索引错乱
常见问题解答
移动前后均可见的行获取Cell的索引选择
你需要使用移动后的最终IndexPath调用 cellForRow(at:) 取Cell。批量更新执行完成后,所有可见Cell的IndexPath已经同步为最终状态,使用移动前的IndexPath会获取到错误的Cell,甚至拿到已被移出视图层级的无效Cell。
现有方案正确性判断
你当前的方案是完全正确的,符合系统的执行逻辑:
- 批量更新的完成块触发时,所有删除、插入、移动操作的视图变更已经全部落地,此时的所有索引都对应最终状态
- 你只需在完成块中用插入、移动后的最终IndexPath匹配
tableView.indexPathsForVisibleRows即可:- 移动前后均可见的行:对应最终IndexPath会出现在可见列表中,可正常获取Cell配置
- 仅移动前可见的行:最终IndexPath不在可见列表,不会执行多余配置
- 仅移动后可见的行:完成块触发时该Cell已经完成加载,可正常获取配置(如果未触发加载说明该Row实际不可见,也无需额外处理)
额外优化建议
- 不要在
performBatchUpdates的更新闭包内执行任何Cell获取、视图配置操作,所有相关逻辑全部放到完成块中,避免索引不同步导致的Crash或异常表现 - 如果你的Cell在
tableView(_:cellForRowAt:)数据源方法中已经完成了全量数据配置,其实只需对移动后仍可见的旧Cell做增量状态更新即可,无需重复配置全量数据,减少性能损耗
内容的提问来源于stack exchange,提问作者Reinhard Männer
相关产品推荐
相关产品推荐

