SwiftUI MapKit 使用协调器 - 如何访问地图 "view" 以调整 "didUpdateLocations" 中的可见区域?

SwiftUI MapKit use of coordinator - how to access map "view" to adjust visible area in "didUpdateLocations"?

我正在使用 SwiftUI MapKit 和协调器方法来获得更多功能。我不确定如何从“didUpdateLocations”委托方法回调更改地图显示的可见区域?不确定如何访问地图视图本身,因此我可以尝试“view.setVisibleMapRect”?

import SwiftUI
import MapKit
import CoreLocation

struct GCMapView {
    var flight : Flight
    
    func createAnnotations(flight : Flight) -> [MKAnnotation] {
        // comment out for this post
        return annotations
    }
    
    func makeCoordinator() -> Coordinator {
        // print("makeCoordinator call - coordinates = ", coordinates.count)
        return Coordinator(self)
    }

    class Coordinator: NSObject, MKMapViewDelegate, CLLocationManagerDelegate {
        var parent: GCMapView
        var locMgr = CLLocationManager()

        init(_ parent: GCMapView) {
            self.parent = parent
            
            super.init()
            locMgr.delegate = self
            locMgr.desiredAccuracy = kCLLocationAccuracyBest
            locMgr.activityType = .otherNavigation
            locMgr.requestWhenInUseAuthorization()
            locMgr.startUpdatingLocation()
        }
        
        // ------------------------------------
        // CLLocationManagerDelegate Functions
        // ------------------------------------

        func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
            guard let lastLoc = locations.last else { return }
            let userCoord : CLLocationCoordinate2D = lastLoc.coordinate
            print("didUpdateLocations - ", userCoord)

            // ?? HOW TO PERFORM A SETVISIBLEMAPREC CALL FROM HERE????
        }
        
        // ------------------------------------
        // MKMapViewDelegate Functions
        // ------------------------------------

        func mapView( _ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
            let renderer = MKPolylineRenderer(overlay: overlay)
            renderer.strokeColor = .blue
            renderer.lineWidth = 1.0
            // renderer.alpha = 1.0
            return renderer
        }
        
    }
    
    
}


extension GCMapView : UIViewRepresentable {
    
    func makeUIView(context: Context) -> MKMapView {
        let map = MKMapView()
        map.delegate = context.coordinator
        map.showsUserLocation = true
        return map
    }

    func updateUIView(_ view: MKMapView, context: Context) {
        
        let annotations = self.createAnnotations(flight: self.flight)
        guard let lastAnnotation = annotations.last else {
            return
        }

        // Add Annotations
        view.addAnnotation(lastAnnotation)
        
        // Add Overlays
        view.removeOverlays(view.overlays)
        let coords = flight.getCoordinates()
        let polyline = MKPolyline(coordinates: coords, count: coords.count)
        view.addOverlay(polyline)
        
        // Zoom
        let mapRect = GCMapHelper.MapRectFromCoords(coords: coords)
        view.setVisibleMapRect(mapRect, edgePadding: UIEdgeInsets(top: 100, left: 100, bottom: 100, right: 100), animated: true)

    }
    
}

您在错误的位置创建了 mapView 变量。您已在 makeUIView(context: Context) 函数中创建它,因此无法在其他任何地方访问它。而是将其声明为结构的参数 GCMapView。然后,您可以根据需要在 locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 中将其引用为 parent.mapView。所以在你的结构中:

struct GCMapView {
    var flight : Flight
    let map = MKMapView()
    ...
}

然后删除

中的声明
func makeUIView(context: Context) -> MKMapView {
    //let map = MKMapView() // Remove this
    map.delegate = context.coordinator
    map.showsUserLocation = true
    return map
}

最后:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let lastLoc = locations.last else { return }
    let userCoord : CLLocationCoordinate2D = lastLoc.coordinate
    print("didUpdateLocations - ", userCoord)

    // ?? HOW TO PERFORM A SETVISIBLEMAPREC CALL FROM HERE????
    parent.map.setVisibleMapRect(mapRect, edgePadding: padding, animated: true)
}