0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Tips]didEndEditingRowAtを扱う際の注意点

Last updated at Posted at 2020-10-21

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に対するアクション
    }
    
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?