Ios 在Swift中在地图上显示路线

Ios 在Swift中在地图上显示路线,ios,swift,Ios,Swift,我正在苹果地图上画两点之间的路线(Swift代码)。 以下结构用于存储坐标 struct GeoLocation { var latitude: Double var longitude: Double func distanceBetween(other: GeoLocation) -> Double { let locationA = CLLocation(latitude: self.latitude, longitude: self.lon

我正在苹果地图上画两点之间的路线(Swift代码)。 以下结构用于存储坐标

struct GeoLocation {
    var latitude: Double
    var longitude: Double

    func distanceBetween(other: GeoLocation) -> Double {
        let locationA = CLLocation(latitude: self.latitude, longitude: self.longitude)
        let locationB = CLLocation(latitude: other.latitude, longitude: other.longitude)
        return locationA.distanceFromLocation(locationB)
    }
}

self.foundLocations - is an array of these structures
在自定义类中,我接收地图上点的坐标

var coordinates = self.foundLocations.map{$0.coordinate}
然后我在地图上画出路线

self.polyline = MKPolyline(coordinates: &coordinates, count: coordinates.count)
        self.mapView.addOverlay(self.polyline, level: MKOverlayLevel.AboveRoads)
为了绘制路线,我从MKMapViewDelegate使用以下方法

func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
    if let polylineOverlay = overlay as? MKPolyline {
        let render = MKPolylineRenderer(polyline: polylineOverlay)
        render.strokeColor = UIColor.blueColor()
        return render
    }
    return nil
}
我得到的是两点之间的一条直线,而不是铺设在道路上的实际路线。
如何显示实际路线?

您实际上必须使用CompletionHandler从Apple地图服务器获取路线

首先为源和目标创建相关的
MKMapItem
s,例如:

let geocoder = CLGeocoder()
let location = CLLocation(latitude: sourceLatitude, longitude: sourceLongitude)

geocoder.reverseGeocodeLocation(location, completionHandler: {
        (placemarks:[AnyObject]?, error:NSError?) -> Void in
        if placemarks?.count > 0 {
            if let placemark: MKPlacemark = placemarks![0] as? MKPlacemark {
                self.source =  MKMapItem(placemark: placemark)
            }
        }
        })
(对目的地重复此操作。)

然后获取
MKRoute
,例如:

let request:MKDirectionsRequest = MKDirectionsRequest()

// source and destination are the relevant MKMapItems
request.setSource(source)
request.setDestination(destination)

// Specify the transportation type
request.transportType = MKDirectionsTransportType.Automobile;

// If you're open to getting more than one route, 
// requestsAlternateRoutes = true; else requestsAlternateRoutes = false;
request.requestsAlternateRoutes = true

let directions = MKDirections(request: request)

directions.calculateDirectionsWithCompletionHandler ({
    (response: MKDirectionsResponse?, error: NSError?) in

    if error == nil {
        self.directionsResponse = response
        // Get whichever currentRoute you'd like, ex. 0
        self.route = directionsResponse.routes[currentRoute] as MKRoute
    }
})
然后,在检索
MKRoute
后,可以将多段线添加到地图中,如下所示:

mapView.addOverlay(route.polyline, level: MKOverlayLevel.AboveRoads)

Swift 3和Lyndsey Scott答案的可重复使用转换:

final class Route {

    static func getRouteFor(
        source: CLLocationCoordinate2D,
        destination: CLLocationCoordinate2D,
        completion: @escaping (

        _ route: MKRoute?,
        _ error: String?)->()

        ) {

        let sourceLocation = CLLocation(

            latitude: source.latitude,
            longitude: source.longitude

        )

        let destinationLocation = CLLocation(

            latitude: destination.latitude,
            longitude: destination.longitude

        )

        let request = MKDirectionsRequest()

        self.getMapItemFor(location: sourceLocation) { sourceItem, error in

            if let e = error {

                completion(nil, e)

            }

            if let s = sourceItem {

                self.getMapItemFor(location: destinationLocation) { destinationItem, error in

                    if let e = error {

                        completion(nil, e)

                    }

                    if let d = destinationItem {

                        request.source = s

                        request.destination = d

                        request.transportType = .walking

                        let directions = MKDirections(request: request)

                        directions.calculate(completionHandler: { response, error in

                            if let r = response {

                                let route = r.routes[0]

                                completion(route, nil)

                            }

                        })

                    }

                }

            }

        }

    }

    static func getMapItemFor(
        location: CLLocation,
        completion: @escaping (

        _ placemark: MKMapItem?,
        _ error: String?)->()

        ) {

        let geocoder = CLGeocoder()

        geocoder.reverseGeocodeLocation(location) { placemark, error in

            if let e = error {

                completion(nil, e.localizedDescription)

            }

            if let p = placemark {

                if p.count < 1 {

                    completion(nil, "placemark count = 0")

                } else {

                    if let mark = p[0] as? MKPlacemark {

                        completion(MKMapItem(placemark: mark), nil)

                    }

                }

            }

        }

    }

}
最终课程路线{
静态函数getRouteFor(
资料来源:CLLocationCoordinate2D,
目的地:CLLocationCoordinate2D,
完成:@转义(
_路线:MKRoute?,
_错误:字符串?->()
) {
让sourceLocation=CLLocation(
纬度:source.latitude,
经度:source.longitude
)
让destinationLocation=CLLocation(
纬度:目的地。纬度,
经度:destination.longitude
)
let request=mkdirectionrequest()
self.getMapItemFor(位置:sourceLocation){sourceItem,中出错
如果让e=错误{
完成(无,e)
}
如果让s=sourceItem{
self.getMapItemFor(位置:destinationLocation){destinationItem,中有错误
如果让e=错误{
完成(无,e)
}
如果设d=目的地{
request.source=s
request.destination=d
request.transportType=.walking
let directions=MKDirections(请求:请求)
计算(completionHandler:{响应,错误在
如果让r=响应{
let route=r.routes[0]
完成(路线,无)
}
})
}
}
}
}
}
静态函数getMapItemFor(
地点:CLLocation,,
完成:@转义(
_placemark:MKMapItem?,
_错误:字符串?->()
) {
让geocoder=CLGeocoder()
地理编码器。反向地理位置(位置){placemark,错误在
如果让e=错误{
完成(无,例如本地化描述)
}
如果设p=placemark{
如果p.count<1{
完成(无,“placemark计数=0”)
}否则{
如果let mark=p[0]为?MKPlacemark{
完成(MKMapItem(placemark:mark),无)
}
}
}
}
}
}
用法:

Route.getRouteFor(source: CLLocationCoordinate2D, destination: CLLocationCoordinate2D) { (MKRoute?, String?) in
       <#code#>
}
Route.getRouteFor(源:CLLocationCoordinate2D,目的地:CLLocationCoordinate2D){(MKRoute?,String?)在
}
您能看到这个错误吗