Swift - Add MKAnnotationView To MKMapView
Asked Answered
O

3

25

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
}
Objectionable answered 28/6, 2014 at 13:43 Comment(4)
See #24524202 for an example using MKPinAnnotationView. You can easily change it to a plain MKAnnotationView and set the image. You don't need a custom annotation class for your purposes (MKPointAnnotation is fine).Clyde
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 #24063009).Clyde
@Anna It works but I can't set the image I tryed with pinView!.image = UIImage(contentsOfFile: "xaxas") and pinView!.image = UIImage(named: "xaxas") added in Images.xcassets but unsuccessfully...Objectionable
UIImage(named:"xaxas") should work and make sure the spelling is exactly right including upper/lower case. Try putting the image with the other project files instead of Images.xcassets. It's also important to create a plain MKAnnotationView instead of MKPinAnnotationView when using custom images.Clyde
C
38

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).

Clyde answered 12/7, 2014 at 12:6 Comment(5)
Remove ! exclamation mark from line - if !(annotation is MKPointAnnotation). Otherwise it will return nil for custom annotation instead of MKPointAnnotation.Jephum
@Kampai, What I would suggest instead is to say if (annotation is MKUserLocation) so it only returns nil for the map view's user location annotation.Clyde
Yes that is right, other wise MKPointAnnotation other than user location also not visible.Jephum
No, it's not that it isn't visible. Returning nil tells the map view to return the default view for the annotation. For MKUserLocation, it's a blue dot. For anything else, it's a red pin. It would be invisible if you return a non-nil MKAnnotationView with no image set.Clyde
Added missing curly bracket back (thanks to @DaniA for pointing this out).Clyde
D
1

You have to show annotation, then you have to add the show annotation method:

let annotation = MKPointAnnotation()
mapVew.showAnnotations([annotation], animated: true)

annotation is an instance of MKPointAnnotation.

Dyanne answered 26/4, 2017 at 12:10 Comment(0)
S
0

1- your map view should delegate itself to your view controller 2- you should implement

func mapView(aMapView: MKMapView!, viewForAnnotation annotation: CustomMapPinAnnotation!) -> MKAnnotationView!

this function is called from every annotation added to your Map

3- subclass your annotations to identify them in the viewForAnnotation method

4- in viewForAnnotation, add

if annotation.isKindOfClass(CustomMapPinAnnotation)
{
  // change the image here
var pinView = aMapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? YourSubclassedAnnotation
  pinView!.image = UIImage(contentsOfFile: "xyz")
}
Sclerosis answered 11/7, 2014 at 13:4 Comment(3)
I get an error "Use of undeclared type CustomMapPinAnnotation"Objectionable
@BogdanBogdanov if you want to use CustomMapPinAnnotation, you must create your own class.Dorking
i need pins dropped with animation , no matter it is custom or default.Sybarite

© 2022 - 2024 — McMap. All rights reserved.