swiftui-gestures

Implement, review, or improve SwiftUI gesture handling. Use when adding tap, long press, drag, magnify, or rotate gestures, composing gestures with simultaneously/sequenced/exclusively, managing transient state with @GestureState, resolving parent/child gesture conflicts with highPriorityGesture or

By dpearson2699 · 3,464 installs

npx skills add dpearson2699/swift-ios-skills --skill swiftui-gestures

Source repository · Upstream listing

SwiftUI Gestures (iOS 26+) Review, write, and fix SwiftUI gesture interactions. Apply modern gesture APIs with correct composition, state management, and conflict resolution using Swift 6.3 patterns. Scope boundary: This skill owns SwiftUI gesture recognition, composition, gesture state, and gesture specific accessibility alternatives. Broader SwiftUI architecture/state ownership belongs in swiftui patterns ; list, scroll, form, and control layout belongs in swiftui layout components ; broad UIKit bridging belongs in swiftui uikit interop . When correcting Apple API availability, deprecation, or behavior claims, cite the relevant Sosumi or official Apple documentation URL in the response. Contents [Gesture Overview]( gesture overview) [TapGesture]( tapgesture) [LongPressGesture]( longpressgesture) [DragGesture]( draggesture) [MagnifyGesture (iOS 17+)]( magnifygesture ios 17) [RotateGesture (iOS 17+)]( rotategesture ios 17) [Gesture Composition]( gesture composition) [ @GestureState ]( gesturestate) [Adding Gestures to Views]( adding gestures to views) [Custom Gesture Protocol]( custom gesture protocol) [Common Mistakes]( common mistakes) [Review Checklist]( review checklist) [References]( references) Gesture Overview Gesture Type Value Since TapGesture Discrete Void iOS 13 LongPressGesture Discrete Bool iOS 13 DragGesture Continuous DragGesture.Value iOS 13 MagnifyGesture Continuous MagnifyGesture.Value iOS 17 RotateGesture Continuous RotateGesture.Value iOS 17 SpatialTapGesture Discrete SpatialTapGesture.Value iOS 16 Discrete gestures fire once ( .onEnded ). Continuous gestures stream updates ( .onChanged , .onEnded , .updating ). TapGesture Recognizes one or more taps. Use the count parameter for multi tap. LongPressGesture Succeeds after the user holds for minimumDuration . Fails if finger moves beyond maximumDistance . With visual feedback via @GestureState + .updating() : Shorthand: .onLongPressGesture(minimumDuration:perform:onPressingChanged:) . DragGesture Tracks finger movement. Value provides startLocation , location , translation , velocity , and predictedEndTranslation . DragGesture.Value.velocity is available with DragGesture from iOS 13+; do not confuse it with iOS 17+ gesture types such as MagnifyGesture and RotateGesture . Configure minimum distance and coordinate space: MagnifyGesture (iOS 17+) Replaces the deprecated MagnificationGesture . Tracks pinch to zoom scale. RotateGesture (iOS 17+) RotateGesture is the newer alternative to RotationGesture . Tracks two finger rotation angle. For persisted, clamped magnification and combined rotation examples, load [references/gesture patterns.md](references/gesture patterns.md). Gesture Composition .simultaneously(with:) — both gestures recognized at the same time The value is SimultaneousGesture.Value with .first and .second optionals. .sequenced(before:) — first must succeed before second begins .exclusively(before:) — only one succeeds (first has priority) @GestureState @GestureState is a property wrapper that automatically resets to its initial value when the gesture ends. Use for transient feedback; use @State for values that persist. Custom reset with animation: @GestureState(resetTransaction: Transaction(animation: .spring)) Adding Gestures to Views Three modifiers control gesture priority in the view hierarchy: Modifier Behavior .gesture() Lower precedence than gestures already defined by the view or its children. .highPriorityGesture() Added gesture takes precedence over existing gestures. .simultaneousGesture() Added gesture processes at the same priority as existing gestures. Use .gesture(parentTap) for the default lower precedence parent gesture, or .highPriorityGesture(parentTap) when the added parent gesture should win. GestureMask Control which gestures participate when using .gesture( :including:) : Custom Gesture Protocol Create reusable gestures by conforming to Gesture : Wrap in a View extension for ergonomic API: Common Mistakes 1. Misreading parent/child gesture precedence Do not assume a parent .gesture() overrides child gestures. Choose the relationship explicitly as shown in [Adding Gestures to Views]( adding gestures to views). 2. Using @State instead of @GestureState for transient state Use @GestureState for values that should reset when recognition ends; keep persistent results in @State . See [ @GestureState ]( gesturestate). 3. Not using .updating() for intermediate feedback 4. Using deprecated gesture types on iOS 17+ 5. Heavy computation in onChanged 6. Using onTapGesture for actions that should be a Button Reserve onTapGesture for multi tap ( count: 2+ ), tap location dependent behavior, or adding tap recognition to non interactive content that already has appropriate accessibility traits. Review Checklist [ ] Correct gesture type: MagnifyGesture / RotateGesture (not deprecated Magnification / Rotation variants) [ ] @GestureState used for transient values that should reset; @State for persisted values [ ] .updating() provides intermediate visual feedback during continuous gestures [ ] Parent/child conflicts resolved with .highPriorityGesture() or .simultaneousGesture() [ ] onChanged closures are lightweight — no heavy computation every frame [ ] Composed gestures use correct combinator: simultaneously , sequenced , or exclusively [ ] Persisted scale/rotation clamped to reasonable bounds in onEnded [ ] Custom Gesture conformances return a gesture body; use AnyGesture<Value when mapping to a custom Value [ ] Gesture driven animations use .spring or similar for natural deceleration [ ] GestureMask considered when mixing gestures across view hierarchy levels [ ] onTapGesture only used where count 1 , tap location, or coordinate space matters — plain single tap actions use Button instead References Read [references/gesture patterns.md](references/gesture patterns.md) when the task needs full drag to reorder, pinch to zoom, combined rotate+scale, velocity/projection, sequenced gesture state machine, or gesture specific UIKit interop examples. [Gesture protocol](https://sosumi.ai/documentation/swiftui/gesture) [TapGesture](https://sosumi.ai/documentation/swiftui/tapgesture) [LongPressGesture](https://sosumi.ai/documentation/swiftui/longpressgesture) [DragGesture](https://sosumi.ai/documentation/swiftui/draggesture) [DragGesture.Value.velocity](https://sosumi.ai/documentation/swiftui/draggesture/value/velocity) [MagnifyGesture](https://sosumi.ai/documentation/swiftui/magnifygesture) [RotateGesture](https://sosumi.ai/documentation/swiftui/rotategesture) [GestureState](https://sosumi.ai/documentation/swiftui/gesturestate) [Composing SwiftUI gestures](https://sosumi.ai/documentation/swiftui/composing swiftui gestures) [Adding interactivity with gestures](https://sosumi.ai/documentation/swiftui/adding interactivity with gestures)