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
的{{1}}将是错误的(等于删除单元格之前的值)。
viewModel.updateSelectionState
是一个结构,因此IndexPath
保留当前值的副本(不是实例)。原始值的任何更新都不会更新捕获的副本。handleDidChangeSelectionState
将不会重新加载tableview的数据源,因此tableView.deleteRows
将不会重新调用。这意味着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()
哪个更好)也许有更好的第三种方法。
谢谢您的任何建议。
答案 0 :(得分:1)
只有第一个方法满足保持平滑动画的第一个条件。在reloadData
之后立即调用deleteRows
会中断动画。
调用indexPath(for: cell)
肯定比重新加载整个表视图便宜。
答案 1 :(得分:0)
请勿使用重新加载特定的行,因为删除行时索引已更改,因此删除行后它将删除动画,这就是为什么您需要重新加载tableview.reloadData()
的原因,这是一个更好的选择。 / p>
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()
})