Kevin
Kevin

Reputation: 1189

Swift 3.0 Map viewForAnnotation Not Outputting Proper Callout

I am having trouble understanding the code for viewForAnnotation method and when it is called. My intention is to display a specific callout depending on what color the pin color is. Upon first loading the mapView, the callouts are displayed properly, however after switching view controllers, the callout buttons are not properly displayed according to the pin color. I have a hunch this might have something to do with when viewForAnnotation is called (whether it is called every time the map appears). I am unable to figure out what is wrong because I am not sure what each part of the code does.

func mapView(_ map: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

if (annotation is MKUserLocation) {

    return nil
}

let identifier = "pinAnnotation"


// In particular I am not sure what the code below does

if let pin = annotation as? ColorPointAnnotation {


    if let view = map.dequeueReusableAnnotationView(withIdentifier: identifier) as? MKPinAnnotationView {
        view.annotation = annotation
        view.pinTintColor = pin.color ?? .purple

        return view

    } else {

        let view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
        view.isEnabled = true

        view.canShowCallout = true

        view.pinTintColor = pin.color ?? .purple

        let btn = UIButton(type: .detailDisclosure)
        view.rightCalloutAccessoryView = btn


        if view.pinTintColor == .red || view.pinTintColor == .green {
            let button = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
            button.setBackgroundImage(UIImage(named: "car"), for: .normal)
            button.addTarget(self, action: #selector(MapVC.getDirections), for: .touchUpInside)
            view.leftCalloutAccessoryView = button
        } else {
            let button = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
            button.setBackgroundImage(UIImage(named: "other"), for: .normal)
            button.addTarget(self, action: #selector(MapVC.other), for: .touchUpInside)
            view.leftCalloutAccessoryView = button
        }

        return view
    }
}

if let annotationView = map.dequeueReusableAnnotationView(withIdentifier: identifier) {
    annotationView.annotation = annotation
    return annotationView
} else {
    let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier: identifier)
    annotationView.isEnabled = true
    annotationView.canShowCallout = true

    let btn = UIButton(type: .detailDisclosure)
    annotationView.rightCalloutAccessoryView = btn

    if annotationView.pinTintColor == .red || annotationView.pinTintColor == .green {

        let smallSquare = CGSize(width: 120, height: 120)
        let button = UIButton(frame: CGRect(origin: CGPoint(x: 0,y :0), size: smallSquare))
        button.setBackgroundImage(UIImage(named: "car"), for: .normal)
        button.addTarget(self, action: #selector(MapVC.getDirections), for: .touchUpInside)
        annotationView.leftCalloutAccessoryView = button
    } else {
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
        button.setBackgroundImage(UIImage(named: "other"), for: .normal)
        button.addTarget(self, action: #selector(MapVC.other), for: .touchUpInside)
        annotationView.leftCalloutAccessoryView = button
    }

    return annotationView
}

}

Upvotes: 0

Views: 345

Answers (1)

Reinier Melian
Reinier Melian

Reputation: 20804

The method func mapView(_ map: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? is a delegate method of MapViewDelegate, this method is executed every time that your mapView show an Annotation in a Region, and if is implemented you can show any subclass of annotationView as annotationView in the map, to show custom callout you need implement this method of MapViewDelegate

//example code
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView){
    let customCallout = CustomCallout(frame: CGRect(x: 0, y: 0, width: self.view.frame.size.width * 0.8, height: 50))
   customCallout.backgroundColor = UIColor.red //your color here
   view.addSubView(customCallout)
   //adjust any param you need here
}

Hope this helps you

Upvotes: 1

Related Questions