计算我的位置和Swift上的MapKit引脚之间的距离
我需要你的帮助,我正在一个应用程序,我有一些针(地点),我想要的是让每个人和我的位置之间的距离。 我的代码如下
let annotation = MKPointAnnotation() let annotationTwo = MKPointAnnotation() let saintPaulHospitalBC = MKPointAnnotation() override func viewDidLoad() { super.viewDidLoad() mapita.showsUserLocation = true // Mapita is the name of the MapView. annotation.coordinate = CLLocationCoordinate2D(latitude: 25.647399800, longitude: -100.334304500) mapita.addAnnotation(annotation) annotationTwo.coordinate = CLLocationCoordinate2D(latitude: 25.589339000, longitude: -100.257724800) mapita.addAnnotation(annotationTwo) saintPaulHospitalBC.coordinate = CLLocationCoordinate2D(latitude: 49.280524700, longitude: -123.128232600) mapita.addAnnotation(SaintPaulHospitalBC) }
当我运行代码时,地图显示了引脚,但是我还能做些什么来开始计算距离? 谢谢!
创build一个帮助函数来计算用户位置和给定的MKPointAnnotation
引脚之间的距离 :
/// Returns the distance (in meters) from the /// user's location to the specified point. private func userDistance(from point: MKPointAnnotation) -> Double? { guard let userLocation = mapita.userLocation.location else { return nil // User location unknown! } let pointLocation = CLLocation( latitude: point.coordinate.latitude, longitude: point.coordinate.longitude ) return userLocation.distance(from: pointLocation) }
最后,为了让用户远离圣保罗医院:
if let distance = userDistance(from: saintPaulHospitalBC) { // Use distance here... }
地理位置跟踪延迟 。 不过,有一个问题:用户距离可能并不总是可用的,因为MapKit / CoreLocation地理位置跟踪可能仍然在后台运行。
解决这个问题的一个方法是遵循MKMapViewDelegate
协议,并在最终计算距离之前等待mapView(_:didUpdate:)
callback 。
你将不得不把你的注释的坐标转换为CLLocationtypes,然后获得它们之间的距离。 要忽略坐标的高度,因为它们是2D,只需使用2D坐标的纬度和经度属性即可:
let loc1 = CLLocation(latitude: coord1.latitude, longitude: coord1.longitude)
但是,CLLocation还有一些其他的属性,如速度和高度,所以如果你想把这些因素考虑在内,你将不得不提供更多的信息。 要find两个位置之间的距离,请执行以下操作:
let distance = loc1.distance(from: loc2)
这会使你的答案成为双倍的米数。
回顾一下,你需要先指定你要找的“距离”。 如果你正在寻找简单的欧几里得距离,那么任何其他的答案或使用distanceFromLocation
将工作。 根据苹果的distanceFromLocation
文件介绍distanceFromLocation
这种方法通过跟踪地球曲率之间的一条直线来测量两个地点之间的距离。 由此产生的弧是平滑的曲线,并没有考虑到两个位置之间的特定高度变化。
这意味着使用这种方法得出的距离不会是两点之间的实际路线/运输距离。 如果那是你正在寻找的,然后转到我上面链接的答案,如果不是,那么继续阅读(但是无论如何,我鼓励你阅读整篇文章:)。
如果您正在寻找地图和地图中其他注释之间的“路线”距离(可驾驶,可步行等),则使用MKRoute
对象将需要更多的工作。 更具体地说,你需要首先访问每个注解的MKMapItem
对象,然后像下面这样的自定义方法能够获得两个MapItem
对象之间的path信息。
注意 – 如果你没有MapItems
那么你可以使用每个注释的坐标来创build它们,比如
ley myCoordinates CLLocationCoordinate2D(latitude: 25.647399800, longitude: -100.334304500) let myPlacemark = MKPlacemark(coordinate: myCoordinates) let myMapItem = MKMapItem(placemark: myPlacemark)
在您的类(或ViewController类)中全局定义一个MKRoutevariables。 这个var
将保存两点之间的计算的路线信息。
var route: MKRoute!
接着
func getDistanceToDestination(srcMapItem srcmapItem: MKMapItem, destMapItem destmapItem: MKMapItem){ let request = MKDirectionsRequest() //create a direction request object request.source = srcmapItem //this is the source location mapItem object request.destination = destmapItem //this is the destination location mapItem object request.transportType = MKDirectionsTransportType.automobile //define the transportation method let directions = MKDirections(request: request) //request directions directions.calculate { (response, error) in guard let response = response else { print(error.debugDescription) return } self.route = response.routes[0] //get the routes, could be multiple routes in the routes[] array but usually [0] is the best route } }
用法是
self.getDistanceToDestination(srcMapItem: yourSourceMapItemObj, destMapItem: yourDestinationMapitemObj)
其中yourSourceMapItemObj
和yourDestinationMapitemObj
是两个MapItem
对象,即源点和目标点。
然后,您可以使用self.route.distance
访问距离,以获取MKRoute
返回的第一条最佳路线的MKRoute
。 MKRoute
对象route
还有一大堆其他的属性,你可以使用它来显示/计算其他东西,我也鼓励你看看这些 。 你可以使用上面的函数来绘制一个ployLine
,也就是在上面的自定义方法的末尾添加self.mapView.add(self.route.polyline)
来self.mapView.add(self.route.polyline)
MapView
两个位置之间的路线,然后使用下面的MKMapViewDelegate
函数来渲染折线。
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { let linerenderer = MKPolylineRenderer(overlay: self.route.polyline) linerenderer.strokeColor = .blue linerenderer.lineWidth = 3.5 return linerenderer }
最后,确保您的类(或您的类扩展名)符合CLLocationManagerDelegate
和MKMapViewDelegate
协议和mapview委托指向self
(我假设您已经这样做)为了上面的一切工作。