UITableViewDelegateのtableView(_:didEndEditingRowAt:)は、セルのスワイプやEditModeを扱う際に触る機会のあるDelegateのAPIですが、注意点が1つあります。
それはスワイプアクションによってセルが削除されても呼ばれる可能性があるという事です。
スワイプによる削除は以下の2種類あると認識しています。
-
tableView(_:commit:forRowAt:)
を実装しつつ、tableView(_:trailingSwipeActionsConfigurationForRowAt:)
をnil
で返している時の標準スワイプ削除 -
tableView(_:trailingSwipeActionsConfigurationForRowAt:)
で削除アクションを含むConfigurationを返している時の独自スワイプ削除
もしかしたら標準スワイプ削除を利用している場合は、内部の挙動によってtableView(_:didEndEditingRowAt:)
が呼ばれないことがあるのかもしれませんが、後者の実装をしている場合は呼ばれることがあります。
そのため、以下のようなコードを書いているとクラッシュします。
func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) {
let indexPath = indexPath!
let cell = tableView.cellForRow(at: indexPath)! // クラッシュ!
// cellに対するアクション
}
独自スワイプ削除でセルを削除した場合、indexPath
自体はnil
ではありませんが、tableView.cellForRow(at: indexPath)
の結果がnil
になりクラッシュします。
また、API設計理由を考えても何かしらの理由でindexPath
自体がnil
で渡されるケースが存在するはずのため、indexPath
のケアも必要です。
このような意図しないクラッシュを避けるために、以下のようにOptional-Bindingを正しく利用して記述しましょう。
func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) {
// もしくはguard-else節など
if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath) {
// cellに対するアクション
}
}