user21138718
user21138718

Reputation:

How do I get the name of the currently selected annotation?

In short, my current code displays annotations with custom images that it gets from another struct, and when the user clicks on an annotation, it brings up another view.

This is my code:


struct MapView: UIViewRepresentable {
    let annotations: [MKPointAnnotation]
    @Binding var showUserView: Bool

    func makeUIView(context: Context) -> MKMapView {
        let mapView = MKMapView(frame: .zero)
        mapView.delegate = context.coordinator
        mapView.showsUserLocation = true
        mapView.userTrackingMode = .followWithHeading
        mapView.mapType = .hybridFlyover
        let region = MKCoordinateRegion(
            center: CLLocationCoordinate2D(latitude: 0, longitude: 0),
            span: MKCoordinateSpan(latitudeDelta: 180, longitudeDelta: 360))
        mapView.setRegion(region, animated: false)
        mapView.showsBuildings = true
        mapView.addAnnotations(annotations)

        // Add gesture recognizer to handle annotation taps
        let gestureRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.annotationTapped))
        mapView.addGestureRecognizer(gestureRecognizer)

        return mapView
    }

    func updateUIView(_ mapView: MKMapView, context: Context) {
        mapView.removeAnnotations(mapView.annotations)
        mapView.addAnnotations(annotations)
    }
func makeCoordinator() -> Coordinator {
    Coordinator(parent: self)
    }

    class Coordinator: NSObject, MKMapViewDelegate {
        let parent: MapView

        init( parent: MapView) {
            self.parent = parent
        }

        // Handle annotation taps by toggling showUserView
        @objc func annotationTapped() {
            parent.showUserView.toggle()
        }

        func mapView( mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            guard let annotation = annotation as? MKPointAnnotation else {
                return nil
            }

            let identifier = "CustomAnnotation"
            var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)

            if annotationView == nil {
                annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
                annotationView?.canShowCallout = true
                annotationView?.image = UIImage(named: "first.png")
            } else {
                annotationView?.annotation = annotation
            }

            return annotationView
        }
    }
}

I tried changing the Coordinator struct with the following code, but then nothing in the tap gesture function worked:

class Coordinator: NSObject, MKMapViewDelegate {
    let parent: MapView
    var selectedAnnotationName: String?

    // ... existing code ...

    // Handle annotation taps by toggling showUserView and setting the selectedAnnotationName
    @objc func annotationTapped(_ sender: UITapGestureRecognizer) {
        if let annotationView = sender.view as? MKAnnotationView, let annotation = annotationView.annotation as? MKPointAnnotation {
            parent.showUserView.toggle()
            selectedAnnotationName = annotation.title ?? ""
        }
    }

    // ... existing code ...
}

Upvotes: 1

Views: 121

Answers (1)

Michael Hulet
Michael Hulet

Reputation: 3499

Currently, that tap gesture recognizer is configured to be fired whenever the user taps anywhere on the map view, not just a specific annotation. However, the method that gets called is expecting the gesture recognizer to be installed on a specific annotation view, which is not the case, so nothing happens

Rather than set up your own tap gesture recognizer, your Coordinator should implement mapView(_:didSelect:), which MapKit calls when the user selected an annotation, and it will give you the view that was tapped. You can do whatever manipulation you'd like from there. If all you need is the annotation itself (not the annotation view) and your build target is at least iOS 16.0, it would probably be even more straightforward to implement the version that takes an MKAnnotation directly

Upvotes: 1

Related Questions