【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 に設定する方法です。
手順としては以下の通りです。
- TableView に長押し検知用のジェスチャー(UILongPressGestureRecognizer)を設定する
- 長押しイベントを検知したら、TableView 上の指が離された位置のセルを取得する
- 長押しされたセルに対して何らかの処理(アラートダイアログを表示など)を行う
実際のコードを以下に示します。
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)
}
}
実際の動作は以下のようになります。

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










