移动或删除UITableView条目后如何重置行以保留隔行变色且不跳转到首行
问题原因
你遇到的失效问题本质是:删除、移动、新增行操作完成后,当前屏幕上已经渲染完成的可见cell对应的行号已经发生了变化,但系统不会自动触发这些已有cell的重新渲染,因此背景色仍然保留了旧行号对应的颜色规则,导致显示错乱。
解决方案
你不需要全量刷新整个列表,也无需调整滚动位置,只要在增删改操作完成后,仅刷新当前屏幕可见的cell即可,用户完全感知不到刷新过程,滚动位置也不会发生任何变化。
第一步:封装刷新可见cell的工具方法
在你的ItemsViewController类中新增一个私有方法,避免重复代码:
private func reloadVisibleCellsForStripe() { guard let visibleIndexPaths = tableView.indexPathsForVisibleRows else { return } // 使用none动画参数,避免刷新时出现闪烁 tableView.reloadRows(at: visibleIndexPaths, with: .none) }
第二步:在三个操作节点调用该方法
分别修改你的新增、删除、移动行的对应方法,在数据和UI操作完成后调用上面的工具方法:
1. 新增行方法修改
@IBAction func addNewItem(_ sender: UIButton){ let newItem = itemStore.createItem() if let index = itemStore.allItems.firstIndex(of: newItem) { let indexPath = IndexPath(row: index, section: 0) tableView.performBatchUpdates({ tableView.insertRows(at: [indexPath], with: .automatic) }, completion: { [weak self] _ in self?.reloadVisibleCellsForStripe() }) } }
2. 删除行方法修改
override func tableView(_ tableView: UITableView, commit editingSytle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingSytle == .delete { let item = itemStore.allItems[indexPath.row] itemStore.removeItem(item) tableView.performBatchUpdates({ tableView.deleteRows(at: [indexPath], with: .automatic) }, completion: { [weak self] _ in self?.reloadVisibleCellsForStripe() }) } }
3. 移动行方法修改
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { itemStore.moveItem(from: sourceIndexPath.row, to: destinationIndexPath.row) reloadVisibleCellsForStripe() }
补充说明
如果你的列表数据量很小(不足百行),也可以直接调用tableView.reloadData()替代上面的可见cell刷新逻辑,reloadData本身不会修改列表当前的滚动偏移量,也不会跳转到第0行,只是性能比仅刷新可见cell稍差一点。
内容的提问来源于stack exchange,提问作者Iggy
相关产品推荐
相关产品推荐

