1

I have been using Mapbox v6 but I got mail from Mapbox to upgrade to v10 for the latest updates.

My app uses Mapbox to show custom maps and show live locations for multiple users. In V6, we have implemented custom Annotations and getting custom annotation view from this mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? method. And then we were changing annotationView.coordinate which was working fine and our map was able to show live location data for every user.

In new v10 SDK, I tried to show PointAnnotation which has fix locations and unable to change. To change location for PointAnnotation, we need to remove that annotation from pointAnnotationManager and then add new annotation with updated location which seems quite weird.

I have also tried to use custom views with V10 and added annotation views based on ViewAnnotationOptions which I am unable to see on my map.

Please check my code here (I am not able to see Annotation View):

private func annotation(at location: CLLocation, forDevice device: String) -> UIView? {
        guard let mapView = self.mapView else { return nil }
        
        let options = ViewAnnotationOptions(
            geometry: Point(location.coordinate),
            width: 100,
            height: 40,
            associatedFeatureId: device,
            allowOverlap: false,
            anchor: .center
        )
        
        guard let userMarker = mapView.viewAnnotations.view(forFeatureId: device) {
            let sampleView = createSampleView(withText: "Hello world!")
            // Added annotation view when it does not exist
            try? mapView.viewAnnotations.add(sampleView, options: options)
            return sampleView
        }

        // Update Annotation's position if already added
        try? mapView.viewAnnotations.update(userMarker, options: options)
        return userMarker
    }

After some modifications to the above code, it worked to show annotation views on the map but randomly it generates multiple annotation views.

private func annotation(at location: CLLocation, forDevice device: String) -> UIView? {
        guard let mapView = self.mapView else { return nil }
        
        let options = ViewAnnotationOptions(
            geometry: Point(location.coordinate),
            width: 100,
            height: 40,
            associatedFeatureId: device,
            allowOverlap: false,
            anchor: .center
        )
        
        if let userMarker = mapView.viewAnnotations.view(forFeatureId: device) {
            // Removed annotation if already exists
            try? mapView.viewAnnotations.remove(userMarker)
        }
        
        // Created new annotation and added again to the map.
        // This seems quite weird as we need to add/remove annotation views just to change location of any annotation.
        let sampleView = createSampleView(withText: "Hello world!")
        try? mapView.viewAnnotations.add(sampleView, options: options)
        //try? mapView.viewAnnotations.update(userMarker, options: options)
        return sampleView
    }

It seems very difficult for me to understand why changing location of annotations is so hard in newer SDK which should have been very easy.

Please suggest me some best solution to update annotation view's locations on the map. I believe adding/removing for multiple annotations will be a costly operation.

NOTE: I am not trying to show current user's location on the map but need to show other users' locations on the map and locations for these annotations need to be updated as any user moves.

Paresh Thakor
  • 1,795
  • 2
  • 27
  • 47

1 Answers1

2

The associatedFeatureId is meant to be used to connect view annotations to a specific feature on the map:

View annotations are not explicitly bound to any sources however ViewAnnotationOptions.associatedFeatureId could be used to bind given view annotation with some Feature by Feature.identifier meaning visibility of view annotation will be driven by visibility of given feature.

Docs

In order to be able to update a view annotation that doesn't have feature id associated you'd need to maintain device<->view mapping.

    private var viewsForDevices = [String: UIView]()

    private func addOrUpdateAnnotationView(at location: CLLocation, forDevice device: String) -> UIView? {
        guard let mapView = self.mapView else { return nil }

        // check if the view for the device already exists
        if let viewAnnotation = viewsForDevices[device] {
            let updateOptions = ViewAnnotationOptions(geometry: Point(location.coordinate)) // update just the location
            try! mapView.viewAnnotations.update(viewAnnotation, options: updateOptions)
            return viewAnnotation
        } else {
            // create an annotation view and add it to the map
            let options = ViewAnnotationOptions(
                geometry: Point(location.coordinate),
                width: 100,
                height: 40,
                allowOverlap: false,
                anchor: .center
            )

            let sampleView = createSampleView(withText: "Hello world!")
            try! mapView.viewAnnotations.add(sampleView, options: options)
            viewsForDevices[device] = view
            return sampleView
        }
    }
evil159
  • 56
  • 2
  • 7