SwiftUI SimultaneousGesture with RotateGesture and MagnifyGesture fails if only one gesture is recognized

I'm trying to combine a RotateGesture and a MagnifyGesture within a single SwiftUI view using SimultaneousGesture. My goal is to allow users to rotate and zoom an image (potentially at the same time). However, I’m running into a problem:

If only one gesture (say, the magnification) starts and finishes without triggering the other (rotation), it seems that the rotation gesture is considered "failed." After that, no further .onChanged or .onEnded callbacks fire for either gesture until the user lifts their fingers and starts over.

Here’s a simplified version of my code:

struct ImageDragView: View {
    @State private var scale: CGFloat = 1.0
    @State private var lastScale: CGFloat = 1.0
    @State private var angle: Angle = .zero
    @State private var lastAngle: Angle = .zero
    
    var body: some View {
        Image("Stickers3")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(height: 100)
            .rotationEffect(angle, anchor: .center)
            .scaleEffect(scale)
            .gesture(combinedGesture)
    }

    var combinedGesture: some Gesture {
        SimultaneousGesture(
            RotateGesture(minimumAngleDelta: .degrees(8)), 
            MagnifyGesture()
        )
        .onChanged { combinedValue in
            if let magnification = combinedValue.second?.magnification {
                let minScale = 0.2
                let maxScale = 5.0
                let newScale = magnification * lastScale
                scale = max(min(newScale, maxScale), minScale)
            }
            if let rotation = combinedValue.first?.rotation {
                angle = rotation + lastAngle
            }
        }
        .onEnded { _ in
            lastScale = scale
            lastAngle = angle
        }
    }
}
  • If I pinch and rotate together (or just rotate), both gestures work as expected.

  • But if I only pinch (or, sometimes, if the rotation amount doesn’t meet minimumAngleDelta), subsequent gestures don’t trigger the .onChanged or .onEnded callbacks anymore, as if the entire gesture sequence is canceled.

I found that setting minimumAngleDelta: .degrees(0) helps because then rotation almost never fails. But I’d like to understand why this happens and whether there’s a recommended way to handle the situation where one gesture might be recognized but not the other, without losing the gesture recognition session entirely.

Is there a known workaround or best practice for combining a pinch and rotate gesture where either one might occur independently, but we still want both gestures to remain active?

Any insights would be much appreciated!

The minimumAngleDelta is the minimum delta required before the gesture starts. By default the minimum delta is a one-degree angle.

I found that setting minimumAngleDelta: .degrees(0) helps because then rotation almost never fails. But I’d like to understand why this happens and whether there’s a recommended way to handle the situation where one gesture might be recognized but not the other, without losing the gesture recognition session entirely.

This sounds more like a case where you want to track a complicated gesture state. For example, you want to require the rotation before the you can magnify the view. If that’s the case, then you might want to model your sequenced gesture states using SequenceGesture. I would suggest you review Composing SwiftUI gestures. It dives into how to combine gestures.

Of if it’s the case where you still want to combine the two gestures but want to give precedence to the first gesture ? In this case use exclusively(before:)

SwiftUI SimultaneousGesture with RotateGesture and MagnifyGesture fails if only one gesture is recognized
 
 
Q