Search code examples
iosswiftmapbox

Using a custom image for the user annotation in MapBox


I'm very new to IOS development so some of this might seem obvious. I've tried combining the examples for customize the user annotation and marking a place on the map with an image

I feel like I need to add the following lines of code and somehow attach this code to the user annotation described in the first link, but I have no idea how to do this. I'm guessing I could also insert some of these functions into the customUserLocationAnnotationView, but there is no obvious indicator of where to place this within that class.

func mapView(_ mapView: MGLMapView, imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? {
var annotationImage = mapView.dequeueReusableAnnotationImage(withIdentifier: "pisa")

if annotationImage == nil {
          var image = UIImage(named: "pisavector")!
          image = image.withAlignmentRectInsets(UIEdgeInsets(top: 0, left: 0, bottom: image.size.height/2, right: 0))
          annotationImage = MGLAnnotationImage(image: image, reuseIdentifier: "pisa")
     }
     return annotationImage
}

func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
     return true
}

EDIT

I don't just want to put an image in a random location like this

enter image description here

I want the image to be centered on the user annotation, and when the user moves, the image will also move, like the image below

enter image description here

As a side note

I'm also getting the error 'Failed to render and update auto auto layout status for ViewController (BYZ-38-tOr): The agent crashed Main.storyboard' but I don't think that's important, because my program still builds and runs on the simulator fine.


Solution

  • override func viewDidLoad() {
        super.viewDidLoad()
        let mapView = MGLMapView(frame: view.bounds)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        mapView.delegate = self
    
        mapView.userTrackingMode = .followWithHeading
        mapView.showsUserHeadingIndicator = true
        view.addSubview(mapView)
    }  
    
    func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
    // Substitute our custom view for the user location annotation. This custom view is defined below.
        if annotation is MGLUserLocation && mapView.userLocation != nil {
            return CustomUserLocationAnnotationView()
        }
        return nil
    }
    
    // Create a subclass of MGLUserLocationAnnotationView.
    class CustomUserLocationAnnotationView: MGLUserLocationAnnotationView {
        ...
    }
    

    Take a look at this example: https://www.mapbox.com/ios-sdk/maps/examples/user-location-annotation/

    There is a method called setupLayers in CustomUserLocationAnnotationView. variable dot is a CALayer, so you can add a UIImage to a CALayer. Change the code in private func setupLayers() like below:

    dot = CALayer()
    let myImage = UIImage(named: "star")?.cgImage
    dot.contents = myImage
    layer.addSublayer(dot)