Search code examples
iosswiftmapkitmapkitannotation

How to register two or more custom annotation views?


I'm trying to register custom annotation views (I create them as a subclass of MKAnnotationView), but I have some trouble with that. Initially, I've tried to register only one custom annotation view for a single annotation marker using the code below (RestaurantMarkerView is my custom annotation view):

 mapView.register(RestaurantMarkerView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)

It works fine (when I tap the pin, it shows the callout). Now I add another annotation marker and try to register another view for it, and as far as I know, in that case I should use custom identifiers for the views, so I do that by this code:

  mapView.register(RestaurantMarkerView.self, forAnnotationViewWithReuseIdentifier: "a")
  mapView.register(ChoosenRestaurantMarkerView.self, forAnnotationViewWithReuseIdentifier: "b")

Now when I tap the markers, they don't show callouts. When I change the reuse identifier of one of the markers to MKMapViewDefaultAnnotationViewReuseIdentifier, that marker shows the callout. So, how can I register multiple custom annotation views? Thanks.


Solution

  • As @Paulw says, you will need to implement the MKMapViewDelegate function mapView(_:viewFor:) to return the appropriate view.

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if annotation is MKUserLocation {
            return nil
        }
    
        if /* condition */ {
            let reuseId = "a"
            var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
            if pinView == nil {
                pinView = RestaurantMarkerView(annotation: annotation, reuseIdentifier: reuseId)
                pinView?.canShowCallout = true
            } else {
                pinView?.annotation = annotation
            }
    
            return pinView
        } else {
            let reuseId = "b"
            var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
            if pinView == nil {
                pinView = ChoosenRestaurantMarkerView(annotation: annotation, reuseIdentifier: reuseId)
                pinView?.canShowCallout = true
            } else {
                pinView?.annotation = annotation
            }
    
            return pinView
        }
    }