TechnologiesSwiftUI

PencilSqueezeGesturePhase enum

iOSmacOStvOSwatchOSvisionOS✓ renders

Describes the phase and value of an Apple Pencil squeeze gesture.

How it works

PencilSqueezeGesturePhase is an enumeration that describes where an Apple Pencil squeeze gesture currently stands in its lifecycle, letting your view distinguish a squeeze that is in progress from one that has just completed. SwiftUI hands you a value of this type as the squeeze gesture moves through its stages, so you can drive transient feedback while the user holds the squeeze and commit an action once they let go. Reach for it whenever you respond to the Pencil's squeeze input and need to know which moment of the gesture you are reacting to rather than treating every callback identically.

  1. Store the current phase in @State

    Because the gesture reports a sequence of phases over time, you keep the latest one in view state so the UI can reflect it. Here @State private var phase: PencilSqueezeGesturePhase = .active holds the value, and the default case in the type means an unhandled phase falls through to an idle state.

  2. Match on the enum cases

    PencilSqueezeGesturePhase is consumed by pattern matching its cases. The computed label uses a switch phase over .active (the squeeze is being held) and .ended (the user released), with default covering any remaining phase, so each value maps to distinct presentation.

  3. Receive the phase from .onPencilSqueeze

    The .onPencilSqueeze modifier is where the symbol plugs in: its closure receives a squeeze value whose phase property is a PencilSqueezeGesturePhase. The closure inspects phaseValue.phase to read the live state of the gesture as it changes.

  4. Commit on the ended phase

    Distinguishing phases lets you separate ongoing feedback from a final action. The example checks if case .ended = phaseValue.phase and only then assigns phase = .ended, so the committing work runs exactly once when the squeeze completes instead of repeatedly while it is .active.

Try it — Add an else branch to the if case .ended check that assigns phase = .active, so the label text updates to "Squeeze active" while the squeeze is held and "Squeeze ended" the moment it is released.

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.

PencilSqueezeGesturePhase.swift
struct PencilSqueezeGesturePhaseDemo: View {
    @State private var phase: PencilSqueezeGesturePhase = .active

    private var label: String {
        switch phase {
        case .active: return "Squeeze active"
        case .ended: return "Squeeze ended"
        default: return "Idle"
        }
    }

    var body: some View {
        VStack(spacing: 12) {
            Image(systemName: "pencil.tip")
                .font(.largeTitle)
                .foregroundStyle(.tint)
            Text(label)
                .font(.headline)
            Text("Squeeze your Apple Pencil to act")
                .font(.caption)
                .foregroundStyle(.secondary)
        }
        .padding()
        .onPencilSqueeze { phaseValue in
            if case .ended = phaseValue.phase {
                phase = .ended
            }
        }
    }
}
Live preview
label Squeeze your Apple Pencil to act
label Squeeze your Apple Pencil to act
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →