Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom clustered annotations on MapKit crash when rapidly dragging the map or changing the zoom-level

After implementing a way to cluster customised annotations, the application crashes whenever the view of the map is adjusted rapidly, by scrolling or changing the zoom-level.

-[MKPointAnnotation memberAnnotations]: unrecognized selector sent to instance 0x281396c00

My guess is that the compiler is trying to retrieve the annotation information, but cannot find the data. As I'm fairly new to Swift, I don't see what I'm missing. Your help would be greatly appreciated.

I have a pretty basic setup to display the map in SwiftUI. In the main file, I call the MapView from MapView.swift

struct MapView: UIViewRepresentable {

    @ObservedObject var store = DataStoreMap()

    func makeCoordinator() -> MapViewCoordinator {
        MapViewCoordinator(self)
    }

    func makeUIView(context: Context) -> MKMapView{
        MKMapView(frame: .zero)
    }

    func updateUIView(_ view: MKMapView, context: Context){

        let location = getUserLocation()
        let chargers = store.chargers

        let coordinate = CLLocationCoordinate2D(latitude: location.latitude, longitude: location.longitude)
        let span = MKCoordinateSpan(latitudeDelta: 0.03, longitudeDelta: 0.03)
        let region = MKCoordinateRegion(center: coordinate, span: span)
        view.setRegion(region, animated: true)

        for charger in chargers {
            let annotation = MKPointAnnotation()
            annotation.coordinate = CLLocationCoordinate2D(latitude: charger.addressInfo.latitude, longitude: charger.addressInfo.longitude)
            view.delegate = context.coordinator
            view.addAnnotation(annotation)
        }

    }
}

Also included in the same file is my custom annotation class.

class MapViewCoordinator: NSObject, MKMapViewDelegate {

    var mapViewController: MapView

    init(_ control: MapView) {
        self.mapViewController = control
    }

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        //Custom View for Annotation
        var annotationView = MKMarkerAnnotationView()
        annotationView.canShowCallout = true

        let identifier = "laadpaal"

        if let dequedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKMarkerAnnotationView {
            annotationView = dequedView
        } else {
            annotationView = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        }

        annotationView.markerTintColor = .some(.systemBlue)
        annotationView.glyphImage = UIImage(named: "car1")
        annotationView.glyphTintColor = .yellow
        annotationView.clusteringIdentifier = identifier

        return annotationView
    }
}
like image 275
unequalsine Avatar asked Oct 26 '25 23:10

unequalsine


1 Answers

The cause for your crash is that you don't account for other annotations requested by map kit (e.g. MKUserLocation). You are triggering this due to the automatic clustering as you set clusteringIdentifier to a non-nil value.

Just return nil when you want to deal with the annotation yourself so MKMapView uses the default handling:

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation is MKUserLocation { return nil }
        if annotation is MKClusterAnnotation { return nil }

        let view = mapView.dequeueReusableAnnotationView(withIdentifier: "identifier", for: annotation)
        view.clusteringIdentifier = "clusterIdentifer"
        // …

        return view
    }

If you ever want to customize the cluster annotations just add a special case for MKClusterAnnotation. And if you show user location don't forget to return nil for MKUserLocation if you want the default blue dot.

like image 83
toto Avatar answered Oct 29 '25 15:10

toto