Why does adding annotations in the updateUIView method of UIViewRepresentable causes stuttering animations in my SwiftUI app?

93 views Asked by At

I am building an app where when the user taps on the bus icon, only bus stop annotations be added on the app. I notice severe stuttering in my view's animations as long as I add annotations in the updateUiView method. Once I remove it, the app is buttery smooth.

Where else can I call this method so that when the user taps on a bus button in swiftUI, only bus annotations are added onto the map?

func updateUIView(_ uiView: MKMapView, context: Context) {
        print("Updating MKMapView")

        if lastViewInStack == .nearbyBusStops {
            uiView.removeAnnotations(uiView.annotations) 
            
            //Adding annotations in updateUIView causes stuttering immediately...
            print("Adding annotations")
            uiView.addAnnotations(getLocations(center: uiView.centerCoordinate))
        } else {
            uiView.removeAnnotations(uiView.annotations)
        }

func getLocations(center: CLLocationCoordinate2D) -> [MKAnnotation] {
        var annotations = [MKAnnotation]()
        
        for busStop in nearbyBusStopsViewModel.nearbyBusStops {
            // Create an annotation
            let annotation = BusStopAnnotation(busStop: busStop)
            annotations.append(annotation)
        }
        
        return annotations
    }

class BusStopAnnotation: NSObject, MKAnnotation {
    let busStop: BusStop
    var coordinate: CLLocationCoordinate2D
    
    init(busStop: BusStop) {
        self.busStop = busStop
        self.coordinate = CLLocationCoordinate2D(latitude: busStop.wrappedLatitude, longitude: busStop.wrappedLongitude)
    }
}
1

There are 1 answers

0
malhal On

The trick with updateUIView is only add the annotations if you have not already added them before. Treat it like a diff. You can do this either with a boolean in a Coordinator or search the map's annotations array if you don't have too many. Currently you are removing and adding new annotations every time updateUIView is called which is a major problem. So change it to something like:

if lastViewInStack == .nearbyBusStops {
        if context.coordinator.alreadyAddedAnnotations == false {
                uiView.removeAnnotations(uiView.annotations) 
            
                //Adding annotations in updateUIView causes stuttering immediately...
                print("Adding annotations")
                uiView.addAnnotations(getLocations(center: uiView.centerCoordinate))
                context.coordinator.alreadyAddedAnnotations = true
            }
        } else {
            uiView.removeAnnotations(uiView.annotations)
            context.coordinator.alreadyAddedAnnotations = false
        }

Also your makeUIView must init and return a new instance of MKMapView, it can also return it from a lazy property in a Coordinator that was init in makeCoordinator.