TechnologiesSwiftUIPencil Interactions

PencilSqueezeGestureValue struct

iOSmacOStvOSwatchOSvisionOS✓ renders

Describes the value of an Apple Pencil squeeze gesture.

How it works

PencilSqueezeGestureValue is the value type SwiftUI delivers to your code each time someone squeezes the barrel of an Apple Pencil Pro. It packages everything you need to react to a squeeze in one snapshot: the current lifecycle phase of the gesture and, where the hardware provides it, the hover pose of the Pencil over the display. Reach for it whenever you want a squeeze to drive an action in your interface, such as toggling a tool palette or confirming a selection, and you need to know whether the gesture is in progress or has finished. You receive an instance through the closure of the onPencilSqueeze(_:) modifier rather than constructing one yourself.

  1. Receive the value from onPencilSqueeze(_:)

    Attaching onPencilSqueeze(_:) to a view registers a handler that SwiftUI calls as the squeeze evolves, passing a fresh PencilSqueezeGestureValue each time. In the example the modifier is applied to the padded VStack and its closure binds the value, so the gesture is observed wherever that view appears on screen.

  2. Read the gesture lifecycle with phase

    The phase property reports where the squeeze sits in its lifecycle, letting you distinguish the moment the gesture begins and continues from the moment it completes. The example switches over value.phase to branch on the gesture's progress.

  3. Branch on the phase cases

    phase is an enumeration whose cases describe the squeeze as it unfolds: an in-progress squeeze versus one that has just released. The example matches .active while the user is squeezing and .ended when they let go, mapping each to a label, and falls through default for any other state.

  4. Drive state from the value

    Because the handler runs on every change, the cleanest pattern is to translate the incoming PencilSqueezeGestureValue into view state and let the body redraw. The example assigns to the @State property phase, which the Text view interpolates as "Squeeze: \(phase)" so the interface reflects the gesture in real time.

Try it — Add a case .changed: arm to the switch over value.phase that sets phase = "Changing" so you can watch the label update continuously while the squeeze is held, instead of only at its start and end.

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.

PencilSqueezeGestureValue.swift
struct PencilSqueezeGestureValueDemo: View {
    @State private var phase = "Idle"

    var body: some View {
        VStack(spacing: 12) {
            Image(systemName: "applepencil")
                .font(.system(size: 44))
                .foregroundStyle(.tint)
            Text("Squeeze: \(phase)")
                .font(.headline)
            Text("Squeeze your Apple Pencil")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .padding()
        .onPencilSqueeze { value in
            switch value.phase {
            case .active: phase = "Active"
            case .ended: phase = "Ended"
            default: phase = "Idle"
            }
        }
    }
}
Live preview
Squeeze: Idle Squeeze your Apple Pencil
Squeeze: Idle Squeeze your Apple Pencil
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →