Search code examples
iosswiftswiftui

`LongPressGesture` not registering on iOS 18


I'm on Xcode 16 beta + iOS 18 following Apple's example on LongPressGesture with:

import SwiftUI

struct LongPressGestureView: View {
    @GestureState private var isDetectingLongPress = false
    @State private var completedLongPress = false

    var body: some View {
        Circle()
            .fill(self.isDetectingLongPress ?
                Color.red :
                (self.completedLongPress ? Color.green : Color.blue))
            .frame(width: 100, height: 100, alignment: .center)
            .gesture(LongPressGesture(minimumDuration: 3)
                .onChanged { value in
                    print("onChanged: \(value)")
                }
                .updating($isDetectingLongPress) {
                    currentState, gestureState, transaction in
                    print("currentState: \(currentState)")
                    print("gestureState: \(gestureState)")
                    print("transaction: \(transaction)")
                    gestureState = currentState
                    transaction.animation = Animation.easeIn(duration: 2.0)
                }
                .onEnded { finished in
                    print("finished: \(finished)")
                    self.completedLongPress = finished
                })
    }
}

The circle is suppose to animate from blue to red then turn green when finished, but it's never red for me. I see it turn green and print finished: true when it ends but I don't ever see any of the other print statements.

Is this a bug or am I missing something obvious?


Solution

  • Could not make Apple example work either, seems to be old code that does not work anymore.

    To achieve what you want you could try this approach:

    struct ContentView: View {
        var body: some View {
            LongPressGestureView()
        }
    }
    
    struct LongPressGestureView: View {
        @State private var isDetectingLongPress = false
        @State private var completedLongPress = false
        
        var body: some View {
            Circle()
                .fill(isDetectingLongPress ? Color.red : (completedLongPress ? Color.green : Color.blue))
                .frame(width: 100, height: 100, alignment: .center)
                .onLongPressGesture(minimumDuration: 2) {
                    completedLongPress = true
                } onPressingChanged: { inProgress in
                    isDetectingLongPress = inProgress
                }
        }
    }