Swift - Add MKAnnotationView To MKMapView

Bogdan Bogdanov picture Bogdan Bogdanov · Jun 28, 2014 · Viewed 39k times · Source

I'm trying to add MKAnnotationView to MKMapView but I can't do it… Can anyone help me?

Here is my code:

override func viewDidLoad() {
    super.viewDidLoad()
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.startUpdatingLocation()
    var latitude:CLLocationDegrees = locationManager.location.coordinate.latitude
    var longitude:CLLocationDegrees = locationManager.location.coordinate.longitude
    var homeLati: CLLocationDegrees = 40.01540192
    var homeLong: CLLocationDegrees = 20.87901079
    var latDelta:CLLocationDegrees = 0.01
    var longDelta:CLLocationDegrees = 0.01
    var theSpan:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta)
    var myHome:CLLocationCoordinate2D = CLLocationCoordinate2DMake(homeLati, homeLong)
    var myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
    var theRegion:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, theSpan)
    self.theMapView.setRegion(theRegion, animated: true)
    self.theMapView.mapType = MKMapType.Hybrid
    self.theMapView.showsUserLocation = true
    ///Red Pin
    var myHomePin = MKPointAnnotation()
    myHomePin.coordinate = myHome
    myHomePin.title = "Home"
    myHomePin.subtitle = "Bogdan's home"
    self.theMapView.addAnnotation(myHomePin)

    var anView:MKAnnotationView = MKAnnotationView()
    anView.annotation = myHomePin
    anView.image = UIImage(named:"xaxas")
    anView.canShowCallout = true
    anView.enabled = true
}

Answer

user467105 picture user467105 · Jul 12, 2014

You need to implement the viewForAnnotation delegate method and return an MKAnnotationView from there.

Here's an example:

func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
    if (annotation is MKUserLocation) {
        //if annotation is not an MKPointAnnotation (eg. MKUserLocation),
        //return nil so map draws default view for it (eg. blue dot)...
        return nil
    }

    let reuseId = "test"

    var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
    if anView == nil {
        anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
        anView.image = UIImage(named:"xaxas")
        anView.canShowCallout = true
    }
    else {
        //we are re-using a view, update its annotation reference...
        anView.annotation = annotation
    }

    return anView
}

Remember you need to create a plain MKAnnotationView when you want to use your own custom image. The MKPinAnnotationView should only be used for the standard pin annotations.

Also note you should not try to access locationManager.location immediately after calling startUpdatingLocation. It may not be ready yet.

Use the didUpdateLocations delegate method.

You also need to call requestAlwaysAuthorization/requestWhenInUseAuthorization (see Location Services not working in iOS 8).