[英]NSFetchedResultsControllerDelegate animating deletion on wrong indexPath
[英]Wrong IndexPath after insertion/deletion of cell from UITableView
VC问题部分的要点:
// Part of VC where cell is setting
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(for: indexPath) as Cell
let cellVM = viewModel.cellVM(for: indexPath)
cell.update(with: cellVM)
cell.handleDidChangeSelectionState = { [weak self] selected in
guard
let `self` = self
else { return }
self.viewModel.updateSelectionState(selected: selected, at: indexPath)
}
return cell
}
// Part of code where cell can be deleted
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let deleteAction = UITableViewRowAction(style: .destructive, title: "delete".localized, handler: { [weak self] _, indexPath in
guard let self = self else { return }
self.viewModel.delete(at: indexPath)
tableView.deleteRows(at: [indexPath], with: .left)
})
return [deleteAction]
}
当细胞已被删除,之后handleDidChangeSelectionState
将参与随后indexPath
传递到viewModel.updateSelectionState
将是错误的(将电池删除之前等于值)。
IndexPath
是一个结构,因此handleDidChangeSelectionState
保留当前值的副本(而不是实例)。 原始值的任何更新都不会更新捕获的副本。 tableView.deleteRows
将不会重新加载tableview的数据源,因此cellForRowAt
将不会重新调用。 这意味着handleDidChangeSelectionState
将不会捕获更新的副本。 询问里面indexPath值handleDidChangeSelectionState
:
cell.handleDidChangeSelectionState = { [weak self, weak cell] selected in
guard
let `self` = self,
let cell = cell,
// now I have a correct value
let indexPath = tableView.indexPath(for: cell)
else { return }
self.viewModel.updateSelectionState(selected: selected, at: indexPath)
}
每次删除后执行reloadData()
:
let deleteAction = UITableViewRowAction(style: .destructive, title: "delete".localized, handler: { [weak self] _, indexPath in
guard let self = self else { return }
self.viewModel.delete(at: indexPath)
tableView.deleteRows(at: [indexPath], with: .left)
// force to recall `cellForRowAt` then `handleDidChangeSelectionState` will capture correct value
tableView.reloadData()
})
哪种方法更好?
我想要:
tableView.deleteRows(at: []
) reloadData()
或indexPath(for cell:)
) 也许有更好的第三种方法。
感谢您的任何建议。
只有第一种方法才能满足第一个条件,以保持动画流畅 。 在deleteRows
中断动画后立即调用reloadData
。
而且,调用indexPath(for: cell)
肯定比重新加载整个表视图便宜。
不要使用重新加载特定的行,因为删除行时索引已更改,并且删除行后它会删除动画,这就是为什么需要重新加载tableview.reloadData()
这是一个更好的选择。
let deleteAction = UITableViewRowAction(style: .destructive, title: "delete".localized, handler: { [weak self] _, indexPath in
guard let self = self else { return }
self.viewModel.delete(at: indexPath)
tableView.deleteRows(at: [indexPath], with: .left)
// force to recall `cellForRowAt` then `handleDidChangeSelectionState` will capture correct value
tableView.reloadData()
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.