iosswiftmkannotationmkannotationview

Custom Annotation for Mapview Swift


I looked at the posts for this and I still do not receive a custom pin....

Custom Annotation --> this includes setting my image

 import UIKit
 import MapKit

 class CustomPointAnnotation: MKPointAnnotation {
     var pinCustomImageName: UIImage!
 }

View Controller:

I want to return current location until a button is selected to drop pin

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    //current Location
    if !(annotation is CustomPointAnnotation) {
        return nil
    }
    let reuseIdentifier = "pin"
    var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
    if annotationView == nil {
        annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
        annotationView!.canShowCallout = true
        
    } else {
        annotationView!.annotation = annotation
    }
    if let annotationView = annotationView {
        annotationView.image = UIImage(named: "Skyscraper")
        annotationView.canShowCallout = true
    }
   
    return annotationView
}

func addPin() {
    pointAnnotation = CustomPointAnnotation()
    pointAnnotation.pinCustomImageName = UIImage(named: "Skyscraper")
    pointAnnotation.coordinate = currentLocation.coordinate
    pointAnnotation.title = "First Building"
    pointAnnotation.subtitle = "Latitude: \(currentLocation.coordinate.latitude), \ 
     (currentLocation.coordinate.longitude)"
    mapView.addAnnotation(pointAnnotation)
}

Solution

  • There's nothing seriously wrong with the code. But there can be a couple of things that would cause problems, including:

    1. Have you set the delegate (either in IB or programmatically) for the map view? If not, your mapView(_:viewFor:) will never be called. Add breakpoint or debugging print statement to confirm.

    2. Have you confirmed that UIImage(named: "Skyscraper") is successfully retrieving an image? Make sure this is not returning nil.


    Note, if only iOS 11 and later, you can simplify this code a bit. Since iOS 11, we no longer need for mapView(_:viewFor:) in simple scenarios like this. I would suggest putting the annotation view configuration code within the annotation view subclass, where it belongs, and avoid cluttering our view controller with a viewFor implementation.

    So when you do get the current issue behind you, the recommended process is:

    1. Define classes for your annotation and annotation view:

      class CustomAnnotation: MKPointAnnotation {
          var pinCustomImage: UIImage!
      }
      

      And

      class CustomAnnotationView: MKAnnotationView {
          override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
              super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
              canShowCallout = true
              update(for: annotation)
          }
      
          override var annotation: MKAnnotation? { didSet { update(for: annotation) } }
      
          required init?(coder aDecoder: NSCoder) {
              fatalError("init(coder:) has not been implemented")
          }
      
          private func update(for annotation: MKAnnotation?) {
              image = (annotation as? CustomAnnotation)?.pinCustomImage
          }
      }
      
    2. In viewDidLoad register this annotation view class:

      mapView.register(CustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)
      
    3. Remove mapView(_:viewFor:) implementation.

    Now when you add a CustomAnnotation to your map’s list of annotations, it will be rendered correctly.

    But I would suggest resolving your current problem first. There’s no point in refining you implementation until these more basic issues are resolved.