iosswiftxcodeswiftuixcode16

The SwiftUI sheet view modifier in the code below doesn't launch on LongPress. Xcode 16.2


In the code below, I want to allow the user to later edit the properties of a selected location in a new View as a sheet view modifier attached to the Map. It's not launching when I long press a previously selected location.

import SwiftUI
import MapKit

struct ContentView: View {
    @State private var userLocations = [UserLocation]()
    @State private var selectedPlace: UserLocation? = nil
    
    let startPosition = MapCameraPosition.region(
        MKCoordinateRegion(
            center: CLLocationCoordinate2D(latitude: 42.196, longitude: 24.747),
            span: MKCoordinateSpan(latitudeDelta: 10, longitudeDelta: 10)
        )
    )
    
    var body: some View {
        MapReader { proxy in
            Map(initialPosition: startPosition) {
                ForEach(userLocations) { location in
                    Annotation(location.name, coordinate: location.coordinate) {
                        Image(systemName: "star.circle")
                            .resizable()
                            .foregroundStyle(.red)
                            .frame(width: 44, height: 44)
                            .background(.white)
                            .clipShape(Circle())
                            .onLongPressGesture {
                                selectedPlace = location
                            }
                    }
                }
            }
            .onTapGesture { position in
                if let coordinate = proxy.convert(position, from: .local) {
                    let newLocation = UserLocation(
                        id: UUID(),
                        name: "New Location",
                        description: "",
                        latitude: coordinate.latitude,
                        longitude: coordinate.longitude
                    )
                    userLocations.append(newLocation)
                }
            }
            .sheet(item: $selectedPlace) { place in
                Text(place.name)
            }
        }
    }
}

Below is the location data struct in a separate Swift file

import Foundation
import MapKit 

struct UserLocation: Codable, Equatable, Identifiable {
    let id: UUID
    var name: String
    var description: String
    var latitude: Double
    var longitude: Double
    
    var coordinate: CLLocationCoordinate2D {
        CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    }
}

I added prints in action places (onTapGesture, onLongPressGesture). The print in onTapGesture executes, and the locations do display on selection.

But no print on onLongPressGesture. Which means the LongPressGesture doesn't get triggered on Long Press. And that's beyond my understanding at the moment.

PS: SwiftUI beginner here. Thanks in advance for your help.


Solution

  • The map is probably recognising your long press as a drag gesture to drag the map. It takes longer for a long press to be recognised compared to a drag gesture. The minimum duration for a long press is probably longer than the minimum duration required for a drag, which in turns is longer than the minimum duration required for a tap. If I set the minimum duration for a long press to be something small, like 0.1, .onLongPressGesture(minimumDuration: 0.1), then the long press is triggered.

    You can fix this by making it detect long presses and drags simultaneously, as opposed to forgetting about the long press as soon as the minimum duration for the drag is reached.

    .simultaneousGesture(LongPressGesture().onEnded { _ in
        selectedPlace = location
    })