元柔道整復師エンジニアBlog

- 元柔道整復師エンジニアBlog -

『 エンジニアをリングする。』

【Swift】TableViewCellの重複タップを防ぎたい(二度押し防止)

TableViewCellを複数回連続で選択した場合において、Cell選択時のイベント処理が複数回呼ばれてしまう。

前提

  • TableViewCellタップ時にVCへ遷移する。
  • tableView:didSelectRowAt内では、負荷の大きいサーバー通信後にVCへの画面遷移を行っている。

今回はTableViewCellを複数回選択した場合に、遷移先のVCが複数回呼ばれ重なって表示されてしまう。

原因としては、
Cell選択時のtableView:didSelectRowAtで負荷の大きいサーバー通信により、
後続処理である画面遷移までに遅延が発生し、その間に次のCell選択イベントが呼ばれてしまっている。

そのため、初回のCell選択イベントが終了する前に
複数のCell選択イベントが発生しているため、これを単一にする必要がある。

対策

その対策として、
初回のCell選択イベント発生時に、イベント終了までTableView全体のタッチイベントを無効にさせる。
isMultipleTouchEnabled または isUserInteractionEnabled
➡ 今回は、タッチイベントのみ対象とすればいいからisMultipleTouchEnabledを使用してみる。

初回または戻ってきた場合において、タッチイベントを有効にしておく。

override func viewWillAppear(_ animated: Bool) {
    tableView.isMultipleTouchEnabled = true
}


現在のCell選択イベント発生の有無により、タッチイベント操作を確定する。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    // Cell選択イベント発生の有無を確認する
    if !tableView.isMultipleTouchEnabled {return}

    // タッチイベントを無効にする
    tableView.isMultipleTouchEnabled = false
    
    // 負荷の大きいサーバー通信処理を仮定して、0.5秒後に実行させる
    DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.5) {
        let vc = NextViewController.init(nibName: "NextViewController", bundle: nil)
        self.navigationController?.pushViewController(vc, animated: true)
    } 
}

イベント発生有の場合 ➡ 処理を中断する。
イベント発生無の場合 ➡ 処理続行しタッチイベントを無効にする。処理終了時にタッチイベントを有効に戻す。

isUserInteractionEnabledの場合であったても同様。

isMultipleTouchEnabled

When set to true, the view receives all touches associated with a multi-touch sequence and starting within the view's bounds. When set to false, the view receives only the first touch event in a multi-touch sequence that start within the view's bounds. The default value of this property is false.


trueに設定すると、ビューはマルチタッチシーケンスに関連付けられていてビューの境界内から始まるすべてのタッチを受け取ります。 falseに設定すると、ビューは、ビューの境界内で始まるマルチタッチシーケンスの最初のタッチイベントのみを受け取ります。このプロパティのデフォルト値はfalseです。

isMultipleTouchEnabled - UIView | Apple Developer Documentation

isUserInteractionEnabled

When set to false, touch, press, keyboard, and focus events intended for the view are ignored and removed from the event queue. When set to true, events are delivered to the view normally. The default value of this property is true.


falseに設定すると、ビューを対象としたtouch、press、keyboard、およびfocusイベントは無視され、イベントキューから削除されます。 trueに設定すると、イベントは通常通りビューに配信されます。このプロパティのデフォルト値はtrueです。
isUserInteractionEnabled - UIView | Apple Developer Documentation

まとめ

実際に動きも確認できた。

参考