Same finger. Same vertical drag. Two Harbor cards inside one ScrollView.
Which one moves?
Idle — both at zero
| Card | Offset | State |
|---|---|---|
| PRIORITY | 0 pt | idle |
| PLAIN | 0 pt | idle |
PRIORITY will use .highPriorityGesture with a sequenced long-press → drag. PLAIN is the control: the same DragGesture via plain .gesture.
Armed — long-press first
LongPressGesture(minimumDuration: 0.35)
.sequenced(before: DragGesture(minimumDistance: 4))
Observed: PHASE ARMED, tape LONGPRESS, PRIORITY detail armed, offset still 0 pt. Sequencing matters — the drag has not started yet.
Priority wins — 72 pt
| Card | Offset | Winner |
|---|---|---|
| PRIORITY | 72 pt | PRIORITY |
| PLAIN | 0 pt | — |
Tape: LONGPRESS · DRAG+72. Footer: P 72 · L 0.
.highPriorityGesture tells the scroll view to yield. The card moves; the list does not.
Plain loses — scroll won
| Card | Offset | Detail |
|---|---|---|
| PRIORITY | 0 pt | idle |
| PLAIN | 0 pt | scroll won |
PHASE PLAIN LOST. WINNER SCROLL. Tape: SCROLL WON.
The control never moved. Vertical intent went to the ScrollView because .gesture(DragGesture()) does not outrank scroll.
The cards share the idea of a vertical drag. Only the attachment changes: highPriorityGesture vs gesture. If your handle refuses to move inside a list, check which modifier you used before rewriting the gesture itself.
Long-press before drag is .sequenced(before:). Simultaneous would try to recognize both at once (pulse while dragging). This bench arms first, then drags — the tape shows LONGPRESS alone before DRAG+72.
Mini-exercise
Swap PRIORITY to plain .gesture and PLAIN to .highPriorityGesture. Re-run. The rose card should be the one that can show a non-zero offset.
Challenges
- Add a third card with
.simultaneousGesture(DragGesture())and photograph whether scroll and drag both fire. - Replace sequencing with simultaneous long-press + drag and show the scale pulse during the drag still.
- Use
.highPriorityGestureon PLAIN but only for horizontal drags (DragGesturethat ignores dy) — vertical should still scroll. - Drive a real finger on device and confirm the scripted 72 pt / SCROLL WON labels match what you feel.
- XCUITest: after
-mode priority, assert static text contains72andWINNER PRIORITY.
Key Points
- Observed idle: both cards 0 pt.
- Observed arm: tape LONGPRESS, PRIORITY armed, still 0 pt.
- Observed priority drag: 72 pt, tape DRAG+72, WINNER PRIORITY.
- Observed plain conflict: 0 pt, WINNER SCROLL, tape SCROLL WON.
.sequenced(before:)arms a drag with a long-press..highPriorityGesturebeatsScrollView; plain.gestureoften loses.- The control is the same
DragGesturewith the priority modifier removed. - If a handle inside a list will not move, check gesture priority before blaming
DragGesture.
Next up: environment and preferences — values travelling down (Environment) and measurements travelling up (PreferenceKey) on one screen, both directions traced.
Read next
Ship your apps faster
When you're ready to publish your Swift app to the App Store, Simple App Shipper handles metadata, screenshots, TestFlight, and submissions — all in one place.
Try Simple App Shipper