私が見ている問題は、.destructive
and pass UIContextualAction
をtrue
で作成するとcompletionHandler
が存在するように見えることです。行を削除するためのデフォルトのアクション。
Xcodeのテンプレートから新しいマスター/詳細アプリを作成し、このコードを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
の結果、行はデフォルトで削除されます。
誰かがこの行動を説明できますか?行が削除されるのはなぜですか?
破壊的オプションのドキュメントによると:
データを削除したり、ある種の破壊的なタスクを実行したりするアクション。
完了は、アクションが成功したかどうかを示すことを意味します。 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
に行が削除されたことが通知されない限り、その後は1行ずつずれます。なんらかの方法で。
Kris Gellci の回答に同意しますが、NSFetchedResultsControllerを使用している場合は、事態が複雑になる可能性があることに注意してください。破壊的なUIContextualActionの場合、completion(true)
を呼び出すと行が削除されるようですが、NSFetchedResultsControllerのデリゲートも削除される可能性があります。そのため、そのようにして簡単にエラーが発生する可能性があります。 NSFetchedResultsControllerを使用して、アクションが成功したかどうかに関係なく、completion(false)
(コンテキストメニューを閉じるため)を呼び出すことにしました。次に、対応するオブジェクトが削除されました。
この問題をiOS13で再現することはできません。iOS12以前の動作はバグであったか、単に取り下げられただけです(おそらく混乱したため)。
IOS 13では、何もせずにcompletion(true)
を呼び出して.destructive
アクションから戻ると、何も起こらず、それで問題は終わりです。セルはnot削除されます。