我看到的问题是,当我用UIContextualAction
创建一个.destructive
并在true
中传递completionHandler
时,似乎有一个删除行的默认操作。
如果您从Xcode的模板创建一个新的Master-Detail应用程序并在MasterViewController
中添加此代码...
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let testAction = UIContextualAction(style: .destructive, title: "Test") { (_, _, completionHandler) in
print("test")
completionHandler(true)
}
return UISwipeActionsConfiguration(actions: [testAction])
}
您要滑动的行将被删除。请注意,没有代码更新表视图。此外,模型不会更新,如果向上滚动导致重新加载行,它将重新出现。
在这种情况下通过false
不会删除该行。或者使用.normal
样式和true
也不会删除行。
.destructive
和true
导致默认删除行。
谁能解释这种行为?为什么要删除行?
根据破坏性选项的文档:
删除数据或执行某种类型的破坏性任务的操作。
完成意味着表明行动是否成功。传递真实意味着破坏性任务是成功的,因此应该删除行。
您需要在发生破坏性操作时手动更新dataSource,否则会导致滚动以重新显示数据。您还需要告诉tableView数据已被删除。
下面是一些显示工作示例的代码:
UIContextualAction(style: .destructive, title: "Delete") { [weak self] (_, _, completion) in
if self?.canDelete(indexPath) { // We can actually delete
// remove the object from the data source
self?.myData.remove(at: indexPath.row)
// delete the row. Without deleting the row or reloading the
// tableview, the index will be off in future swipes
self?.tableView?.deleteRows(at: [indexPath], with: .none)
// Let the action know it was a success. In this case the
// tableview will animate the cell removal with the swipe
completion(true)
} else { // We can't delete for some reason
// This resets the swipe state and nothing is removed from
// the screen visually.
completion(false)
}
}
然后我需要重新加载tableview
或调用deleteRows
,以便在下次滑动时正确计算indexPath
。
如果我有10行并且我将第5行拖动以删除,除非重新加载tableview
或者tableview
被告知以某种方式删除了行,否则之后的每一行将被关闭一行。
我同意Kris Gellci的回答,但请注意,如果你使用的是NSFetchedResultsController,它可能会使事情复杂化。似乎对于破坏性的UIContextualAction,调用completion(true)
将删除该行,但NSFetchedResultsController的委托也是如此。因此,您可以轻松地以这种方式结束错误。使用NSFetchedResultsController,我决定调用completion(false)
(使上下文菜单关闭),无论操作是否成功,然后让代理人在删除相应对象时处理删除表行。