【问题标题】:MapKit: Route not being displayed between two annotationsMapKit:两个注释之间未显示路线
【发布时间】:2020-03-05 06:23:13
【问题描述】:

我试图显示两个注释之间的路线。

注释和区域工作正常,但路线不会显示,我不知道为什么 看起来路线根本没有被渲染。 我确定该路线存在,因为我尝试打印它并且它位于directionResponse.routes 有什么建议吗?

我正在使用 SwiftUI

然后这包含在父视图中。

import SwiftUI
import MapKit
import FirebaseFirestore

struct MapView: UIViewRepresentable {
    var packageLocation: GeoPoint
    var destination: GeoPoint
    var driverLocation = CLLocationCoordinate2D()

    func makeUIView(context: UIViewRepresentableContext<MapView>) -> MKMapView {
        MKMapView()
    }

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


    func updateUIView(_ uiView: MKMapView, context: UIViewRepresentableContext<MapView>) {
        let requestLocation: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: packageLocation.latitude, longitude: packageLocation.longitude)
        let destinationLocation: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: destination.latitude, longitude: destination.longitude)

        //let span = MKCoordinateSpan(latitudeDelta: 1, longitudeDelta: 1)
        //let region = MKCoordinateRegion(center: requestLocation, span: span)
        //uiView.setRegion(region, animated: true)

        let annotation = MKPointAnnotation()
        annotation.coordinate = requestLocation
        annotation.title = "Package Title"
        uiView.addAnnotation(annotation)

        let annotation2 = MKPointAnnotation()
        annotation2.coordinate = destinationLocation
        annotation2.title = "Destiantion"
        uiView.addAnnotation(annotation2)

        let sourcePlacemark = MKPlacemark(coordinate: requestLocation)
        let destinationPlacemark = MKPlacemark(coordinate: destinationLocation)


        let directionRequest = MKDirections.Request()
        directionRequest.source = MKMapItem(placemark: sourcePlacemark)
        directionRequest.destination = MKMapItem(placemark: destinationPlacemark)
        directionRequest.transportType = .automobile

        let directions = MKDirections(request: directionRequest)

        directions.calculate { (response, error) in
            guard let directionResponse = response else {
                if let error = error {
                    print(error.localizedDescription)
                }
                return
            }
            print(directionResponse)

            let route = directionResponse.routes[0]
            uiView.addOverlay(route.polyline, level: .aboveRoads)

            let rect = route.polyline.boundingMapRect
            uiView.setRegion(MKCoordinateRegion(rect), animated: true)
        }

    }
}

【问题讨论】:

    标签: ios swift mapkit swiftui swift5


    【解决方案1】:

    你几乎得到它。

    您需要解决的一个问题是使用MKMapView 委托函数。

    最简单的方法是继承MKMapView 并制作符合MKMapViewDelegate 的地图视图。

    首先,创建自己的地图视图,继承MKMapView 并符合MKMapViewDelegate。目前您只真正使用了rendererFor overlay 委托方法,所以我将实现它,但您可以根据需要添加其他方法。

    class WrappableMapView: MKMapView, MKMapViewDelegate {
    
        func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
            let renderer = MKPolylineRenderer(overlay: overlay)
            renderer.strokeColor = .red
            renderer.lineWidth = 4.0
            return renderer
        }
    }
    

    然后您需要更新您的UIViewRepresentable 以使用您刚刚创建的新WrappableMapView。我已经制作了一个功能示例,所以在这里我传递了请求和目标位置。你可以随心所欲地处理它,但至少这会给你一些有用的东西。

    struct MyMapView: UIViewRepresentable {
    
        @Binding var requestLocation: CLLocationCoordinate2D
        @Binding var destinationLocation: CLLocationCoordinate2D
    
        private let mapView = WrappableMapView()
    
        func makeUIView(context: UIViewRepresentableContext<MyMapView>) -> WrappableMapView {
            mapView.delegate = mapView // make sure we set our delegate to be the mapView we just created
            return mapView
        }
    
        func updateUIView(_ uiView: WrappableMapView, context: UIViewRepresentableContext<MyMapView>) {
    
            let requestAnnotation = MKPointAnnotation()
            requestAnnotation.coordinate = requestLocation
            requestAnnotation.title = "Package Title"
            uiView.addAnnotation(requestAnnotation)
    
            let destinationAnnotation = MKPointAnnotation()
            destinationAnnotation.coordinate = destinationLocation
            destinationAnnotation.title = "Destination"
            uiView.addAnnotation(destinationAnnotation)
    
            let requestPlacemark = MKPlacemark(coordinate: requestLocation)
            let destinationPlacemark = MKPlacemark(coordinate: destinationLocation)
    
            let directionRequest = MKDirections.Request()
            directionRequest.source = MKMapItem(placemark: requestPlacemark)
            directionRequest.destination = MKMapItem(placemark: destinationPlacemark)
            directionRequest.transportType = .automobile
    
            let directions = MKDirections(request: directionRequest)
            directions.calculate { response, error in
                guard let response = response else { return }
    
                let route = response.routes[0]
                uiView.addOverlay(route.polyline, level: .aboveRoads)
    
                let rect = route.polyline.boundingMapRect
                uiView.setRegion(MKCoordinateRegion(rect), animated: true)
    
                // if you want insets use this instead of setRegion
                //  uiView.setVisibleMapRect(rect, edgePadding: .init(top: 50.0, left: 50.0, bottom: 50.0, right: 50.0), animated: true)
            }
    
        }
    }
    

    最后,我们可以将它们与表明它有效的 ContentView 放在一起:

    struct ContentView: View {
    
        @State var requestLocation = CLLocationCoordinate2D(latitude: 51.509865, longitude:  -0.118092)
        @State var destinationLocation = CLLocationCoordinate2D(latitude: 51.501266, longitude: -0.093210)
    
        var body: some View {
            MyMapView(requestLocation: $requestLocation, destinationLocation: $destinationLocation)
        }
    }
    

    它应该是这样的:


    有一点需要注意,在模拟器中使用rendererFor overlay 委托函数会导致error。这只发生在模拟器中而不是设备上,所以如果您在控制台中看到这样的错误消息,请不要感到惊讶。

    2019-11-08 18:50:30.034066+0000 StackOverflow[80354:9526181] Compiler error: Invalid library file
    

    【讨论】:

    • 非常感谢,您知道如何向MKCoordinateRegion 添加跨度,这样它们就不会显示在屏幕边缘吗?
    • 是的,我在updateUIView的末尾添加了一个替代项
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多