@Mir’s answer was absolutely correct. But you could also do it the following way.
As you will see, all gestures fire simultaneously.
The real problem here is the SwiftUI ‘design’ choice that I would rather consider a bug.
Just try to touch the same view a second time while you are dragging and your first gesture will stop updating and even leave you dangling without an .onEnded callback. The new (second) gesture does not fire any callback at all, it’s non-existent and just kills your first gesture!!! So no way to establish a decent state machine, sorry :-)
Yet another (third) touchDown spins up a correctly functioning new drag gesture, totally ignorant of the first two attempts, even if you didn’t release the finger(s) from gesture one and two, and they are still on the screen ;-)
That is the reason why 2 finger gestures like rotation and magnification don’t fire simultaneously with 1 finger drag gestures because the first subsequent touch after a (single finger) drag kills the whole drag gesture.
It has nothing to do with the rotation/magnification gestures per se…
_
struct ContentView: View {
@GestureState var state: DragGesture.Value?
var body: some View {
let drag3 = DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged { gesture in print("DRAG 3 - onChanged \(gesture.startLocation)") }
.onEnded { gesture in print("DRAG 3 - onEnded \(gesture.startLocation)") }
.updating($state) { value, _, _ in print("DRAG 3 - updating \(value.startLocation)") }
let drag2 = DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged { gesture in print("DRAG 2 - onChanged \(gesture.startLocation)") }
.onEnded { gesture in print("DRAG 2 - onEnded \(gesture.startLocation)")}
.updating($state) { value, _, _ in print("DRAG 2 - updating \(value.startLocation)")}
.simultaneously(with: drag3)
let drag1 = DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged { gesture in print("DRAG 1 - onChanged \(gesture.startLocation)") }
.onEnded { gesture in print("DRAG 1 - onEnded \(gesture.startLocation)") }
.updating($state) { value, _, _ in print("DRAG 1 - updating \(value.startLocation)") }
.simultaneously(with: drag2)
HStack() {
Rectangle()
.fill(Color.red)
.frame(width: 200, height: 200)
.gesture(drag1)
//.simultaneousGesture(drag1)
//.simultaneousGesture(drag2)
//.simultaneousGesture(drag3)
}
}
}