TechnologiesSwiftUI

LongPressGesture struct

iOSmacOStvOSwatchOSvisionOSiOS 13.0+✓ renders

A gesture that succeeds when the user performs a long press.

How it works

LongPressGesture recognizes a press-and-hold interaction: the user must keep a finger (or pointer) down on a view for a sustained period before the gesture succeeds. It exists for the common case where a tap is too easy to trigger by accident and you want a deliberate, time-gated action — revealing a context menu, confirming a destructive operation, or entering an edit mode. Reach for it whenever a momentary touch isn't intent enough and you need the system to wait for the user to commit. Like other gestures, you create it, attach callbacks, and apply it to a view with the gesture(_:) modifier.

  1. Set the hold threshold with minimumDuration

    The initializer takes a minimumDuration that defines how long, in seconds, the press must be held before the gesture is recognized. A longer value demands a more deliberate hold; a shorter one fires almost like a tap. Here the gesture is created as LongPressGesture(minimumDuration: 1.0), requiring a full second of contact before it succeeds.

  2. Respond to success with onEnded

    onEnded registers a closure that runs when the gesture completes — that is, once the press has been held for the required duration. This is where you perform the resulting action. In the example .onEnded { _ in completed.toggle() } flips the completed state, which in turn drives the view's fill color, scale, and label.

  3. Attach the gesture to a view

    A LongPressGesture only takes effect once it is bound to a view through the gesture(_:) modifier, which makes that view the touch target for recognition. The example applies it to a Circle() via .gesture(...), so pressing and holding the circle is what arms and ultimately triggers the gesture.

  4. Reflect gesture state through SwiftUI bindings

    Because onEnded mutates @State, the recognized long press flows naturally into the rest of the view. Toggling completed re-evaluates dependent modifiers like .fill(completed ? Color.green : Color.gray) and .scaleEffect(...), and updates the Text from "Press and hold" to "Long press recognized" — giving the user immediate feedback that the hold registered.

Try it — Change minimumDuration: 1.0 to minimumDuration: 3.0 and feel how much longer you must hold the circle before onEnded fires and the label flips.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

LongPressGesture.swift
struct LongPressGestureDemo: View {
    @State private var completed = true

    var body: some View {
        VStack(spacing: 16) {
            Circle()
                .fill(completed ? Color.green : Color.gray)
                .frame(width: 120, height: 120)
                .scaleEffect(completed ? 1.2 : 1.0)
                .gesture(
                    LongPressGesture(minimumDuration: 1.0)
                        .onEnded { _ in completed.toggle() }
                )
            Text(completed ? "Long press recognized" : "Press and hold")
                .font(.headline)
        }
        .padding()
    }
}
Live preview
Long press recognized
Long press recognized
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →