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.
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 = .activeholds the value, and thedefaultcase in the type means an unhandled phase falls through to an idle state.Match on the enum cases
PencilSqueezeGesturePhase is consumed by pattern matching its cases. The computed
labeluses aswitch phaseover.active(the squeeze is being held) and.ended(the user released), withdefaultcovering any remaining phase, so each value maps to distinct presentation.Receive the phase from .onPencilSqueeze
The
.onPencilSqueezemodifier is where the symbol plugs in: its closure receives a squeeze value whosephaseproperty is a PencilSqueezeGesturePhase. The closure inspectsphaseValue.phaseto read the live state of the gesture as it changes.Commit on the ended phase
Distinguishing phases lets you separate ongoing feedback from a final action. The example checks
if case .ended = phaseValue.phaseand only then assignsphase = .ended, so the committing work runs exactly once when the squeeze completes instead of repeatedly while it is.active.
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.
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
}
}
}
}