Long press on UITableView
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Adding a long-press action to a UITableView is a common way to expose extra options such as rename, delete, share, or preview. The basic pattern is to attach a UILongPressGestureRecognizer to the table view, translate the touch location into an index path, and respond only once when the gesture enters the .began state.
Add a UILongPressGestureRecognizer
Start by attaching the gesture recognizer in your view controller:
The recognizer is attached to the table view itself, not to each cell. That keeps the implementation simple and works naturally with reused cells.
Map the Touch to a Row
The handler should convert the press location into an IndexPath:
Using .began is important. A long-press recognizer transitions through several states, and responding on every state change can trigger duplicate actions for a single press.
Present an Action Sheet
In many apps, the long press opens options for the selected row:
Then call presentActions(for:at:) from handleLongPress.
This pattern keeps the gesture code focused on input recognition while the UI decision stays in a separate helper.
Handle Selection and Gesture Conflicts
Long press and normal row selection can coexist, but you should think about the interaction:
- tap selects or opens
- long press shows more actions
If you find the table is feeling too sensitive, tune minimumPressDuration or allowableMovement:
That helps prevent accidental long-press recognition while the user is simply scrolling or tapping.
Use Haptics for Better Feedback
Long press feels better when the user gets immediate feedback:
Trigger the haptic once the gesture is recognized. It makes the interaction feel intentional rather than vague.
Consider UIContextMenuInteraction on Newer iOS
For newer iOS versions, context menus are often a better fit than a custom long-press action sheet. However, a long-press recognizer is still useful when:
- you support older patterns
- you need custom behavior unrelated to menus
- you want direct control over gesture timing
The important point is to choose the interaction that matches the product, not just the first API you remember.
Common Pitfalls
- Handling every recognizer state instead of only
.began, which causes duplicate actions. - Trying to add separate long-press recognizers to each cell and fighting cell reuse.
- Ignoring the case where the user presses empty space and
indexPathForRow(at:)returnsnil. - Making the press duration too short and accidentally interfering with normal scrolling.
- Packing all business logic directly into the gesture handler instead of forwarding to a dedicated action method.
Summary
- Add one
UILongPressGestureRecognizerto the table view, not one per cell. - Convert the touch location into an index path to identify the pressed row.
- React only when the recognizer enters the
.beganstate. - Use the gesture to present actions or context-specific UI for the selected item.
- Tune the recognizer so long press complements normal table interaction instead of fighting it.

