ios - MapKit:两个注释之间未显示路线
问题描述
我试图显示两个注释之间的路线。
注释和区域工作正常,但路线不会显示,我不知道为什么看起来路线根本没有被渲染。我确定该路线存在,因为我尝试打印它并且它在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)
}
}
}
解决方案
你几乎明白了。
您需要解决的一个问题是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
在模拟器中使用委托函数会导致错误。这只会发生在模拟器中而不是设备上,因此如果您在控制台中看到这样的错误消息,请不要感到惊讶。
2019-11-08 18:50:30.034066+0000 StackOverflow[80354:9526181] Compiler error: Invalid library file
推荐阅读
- c++ - 如何在链表的第n个位置添加一个项目?
- symfony - 如何使用 symfony/mailer 和 symfony/mailgun-mailer 提供商标记电子邮件
- python - 求数效率平方根的算法
- javascript - 动画总是触发,因为状态总是在 React 中滚动时发生变化
- vuejs2 - vee-validate 3 的有效格式是什么?
- android - 如何在改造中解析 Restfull api JSON 响应?
- mongodb - 聚合一个 MongoDB 数组只返回多个元素数组
- typescript - 如何使用 jest 在模拟响应中获取响应状态?
- sql-server - SQL 语法 1.* 这是什么意思?
- java - TestContainers PostgreSQLContainer 与 Kotlin 单元测试:“没有足够的信息来推断类型变量 SELF”