HomeiOS Developmentios - Problem with MKCoordinateRegion Middle not updating when consumer interacts with...

ios – Problem with MKCoordinateRegion Middle not updating when consumer interacts with MapViewRepresentable in SwiftUI


I’m at the moment utilizing a MapViewRepresentable in SwiftUI, which conforms to UIViewRepresentable and makes use of an MKMapView to show annotations on a map. The MapViewRepresentable takes a Binding for mapRegion, which is initially set to a default worth.

Nonetheless, I observed that if I work together with the map (e.g., pan, zoom), the mapRegion binding in my ViewModel does not get up to date routinely. To resolve this, I applied the mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) technique within the Coordinator, updating the mapRegion binding with the present map’s area. This is the code I am utilizing:

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
DispatchQueue.essential.async {
    self.mum or dad.mapRegion = mapView.area
} }

This resolution works as anticipated, however I noticed that the view appears to replace itself a number of instances throughout this course of. The annotation animations triggered by the area change happen thrice, which gives the look of a number of state modifications.

I want to know if there’s a higher method to maintain my mapRegion binding up to date with out triggering a number of pointless view updates. Is there a extra environment friendly and simple option to obtain this? Any insights or options are enormously appreciated. Thanks!

That is the UIViewRepresentable:

struct MapViewRepresentable: UIViewRepresentable {
@Binding var mapRegion: MKCoordinateRegion
var locations: [Place]
var onTap: (String) -> Void = { _ in }

func makeUIView(context: Context) -> MKMapView {
    let mapView = MKMapView()
    mapView.delegate = context.coordinator
    mapView.showsUserLocation = true
    mapView.showsCompass = true
    return mapView
}

func updateUIView(_ uiView: MKMapView, context: Context) {
    uiView.setRegion(mapRegion, animated: true)
    updateAnnotations(from: uiView)
}


func makeCoordinator() -> Coordinator {
    Coordinator(self)
}

non-public func updateAnnotations(from mapView: MKMapView) {
    mapView.removeAnnotations(mapView.annotations)
    mapView.addAnnotations(locations)
}

class Coordinator: NSObject, MKMapViewDelegate {
    var mum or dad: MapViewRepresentable

    init(_ mum or dad: MapViewRepresentable) {
        self.mum or dad = mum or dad
    }
    
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        guard let placeAnnotation = annotation as? Place else {
            return nil
        }

        let annotationView = MKMarkerAnnotationView(annotation: placeAnnotation, reuseIdentifier: "placeAnnotation")
        annotationView.canShowCallout = false
        annotationView.animatesWhenAdded = true
        annotationView.markerTintColor = placeAnnotation.chosen ? UIColor(named: "TripBlue") : Colour(hex: placeAnnotation.coloration)?.uiColor
        annotationView.glyphImage = UIImage(systemName: placeAnnotation.icon)
        annotationView.glyphTintColor = .white
        return annotationView
    }

    func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped management: UIControl) {
        if let _ = view.annotation as? Place {
        }
    }
    
    func mapView(_ mapView: MKMapView, didSelect annotation: MKAnnotation) {
        guard let placeAnnotation = annotation as? Place else {
            return
        }
        self.mum or dad.onTap(placeAnnotation.id ?? "")
    }
    
    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
        DispatchQueue.essential.async {
            self.mum or dad.mapRegion = mapView.area
        }
        
    }
    
}}

This id the use on SwiftUIView

 @ObservedObject var exploreMapViewModel: ExploreMapViewModel = ExploreMapViewModel()

@ViewBuilder func generateMap() -> some View {
    MapViewRepresentable(mapRegion: $exploreMapViewModel.mapRegion, locations: exploreMapViewModel.annotationList, onTap: { id in
        withAnimation {
            exploreMapViewModel.selectPlace(id: id, zoom: exploreMapViewModel.mapRegion.span.longitudeDelta)
            exploreMapViewModel.scrollTo(id: id)
        }
    })
}

That is the declaration in ViewModel

 @Revealed var mapRegion = MKCoordinateRegion(middle: CLLocationCoordinate2D(latitude: 4.676490, longitude: -74.086259), span: MKCoordinateSpan(latitudeDelta: 0.03, longitudeDelta: 0.03))

I actually recognize your assist. Thanks

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments