【Swift】TableView で長押しを検知してメニューやアラートダイアログを表示する簡単な方法・手順の備忘録【Xcode】

UITableView で長押しを検知したい

iOS アプリでリストを長押しした時に何らかの処理をしたいケースは多いと思います。

例えば以下のような用途ですね。

  • 長押しされたリストアイテムに対する操作メニューを表示する
  • アラートダイアログを表示する
  • リストを編集モードにする

UITableView に対する長押し操作を検知するための方法として、本記事では2つの方法をご紹介したいと思います。

1つ目の方法:メニューを表示する

長押しされたセルに対し、UIContextMenu という標準のメニューを表示する方法です。

こちらは、お馴染み UITableViewDelegate の tableView(_:contextMenuConfigurationForRowAt:point:) を実装することで簡単に対応することができます。

実際のコードを以下に示します。

//
// ViewController に UITableViewDelegate プロトコルを実装する
extension ContextMenuSampleViewController: UITableViewDelegate {
    /// セル長押し時にコンテキストメニューを表示する
    func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
        
        let firstMenuAction = UIAction(title: "最初のメニュー", image: nil, identifier: nil, discoverabilityTitle: nil) { _ in
            print("メニュー選択時の処理")
        }
        let lastMenuAction = UIAction(title: "最後のメニュー", image: nil, identifier: nil, discoverabilityTitle: nil) { _ in
            print("メニュー選択時の処理")
        }
        
        let menu = UIMenu(title: "メニュー", image: nil, identifier: nil, options: [], children: [firstMenuAction, lastMenuAction])
        let contextMenuConfiguration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
            menu
        }
        
        return contextMenuConfiguration
    }
}

実際の動作は以下のような感じになります。

2つ目の方法:TableView に UILongPressGestureRecognizer を設定する

こちらの方法は、UIGestureRecognizer の一つである UILongPressGestureRecognizer を TableView に設定する方法です。

手順としては以下の通りです。

  1. TableView に長押し検知用のジェスチャー(UILongPressGestureRecognizer)を設定する
  2. 長押しイベントを検知したら、TableView 上の指が離された位置のセルを取得する
  3. 長押しされたセルに対して何らかの処理(アラートダイアログを表示など)を行う

実際のコードを以下に示します。

    override func viewDidLoad() {
        super.viewDidLoad()
      
        // TableView に長押し検知のためのジェスチャーを初期化
        let longTap = UILongPressGestureRecognizer(target: self, action: #selector(longTap))
        // ロングタップを検出するまでの時間を指定
        longTap.minimumPressDuration = 0.5
        // 指のずれを許容する
        longTap.allowableMovement = 10
        // TableView にジェスチャーを追加する
        tableView.addGestureRecognizer(longTap)
    }

    // TableView に対する長押し操作イベント検知時に呼ばれる
    @objc func longTap(sender: UILongPressGestureRecognizer) {
        // 長押し判定時のみ処理する
        guard sender.state == .began else { return }
        // 指が離された位置を取得して、その位置の IndexPath を取得する
        let touchPoint = sender.location(in: tableView)
        if let indexPath = tableView.indexPathForRow(at: touchPoint) {
            print(indexPath.description)
            
            // 確認用にアラートを表示
            showMessage(title: "長押し検知!", message: "\(indexPath.row)", tapOk: nil)
        }
    }

実際の動作は以下のようになります。

おわりに

本記事で紹介した実装のサンプルコードを以下に公開しているので、興味のある方はご参照ください。

TableViewLongTapSample

参考文献

UIContextMenuConfiguration
UILongPressGestureRecognizer