【发布时间】:2019-02-27 08:49:33
【问题描述】:
代码
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 将参与其中,那么传递给 viewModel.updateSelectionState 的 indexPath 将是错误的(将等于删除单元格之前的值)。
我想我知道为什么
-
IndexPath是一个结构,所以handleDidChangeSelectionState保留当前值的副本(不是实例)。原始值的任何更新都不会更新捕获的副本。 -
tableView.deleteRows不会重新加载 tableview 的数据源,所以cellForRowAt不会召回。这意味着handleDidChangeSelectionState不会捕获更新的副本。
解决这个问题的方法
* 第一
询问handleDidChangeSelectionState里面的indexPath值:
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:))
也许有更好的第三种方法。
感谢您的任何建议。
【问题讨论】:
标签: ios swift uitableview