在Swift中显示地图上的路线

时间:2015-02-25 15:52:56

标签: ios swift

我试图在Apple地图上的两点之间绘制路线(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
}

而不是实际铺设在道路上的路线,我只得到两点之间的直线。 如何显示实际路线?

2 个答案:

答案 0 :(得分:6)

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

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

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)

答案 1 :(得分:0)

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)

                    }

                }

            }

        }

    }

}

用法:

Route.getRouteFor(source: CLLocationCoordinate2D, destination: CLLocationCoordinate2D) { (MKRoute?, String?) in
       <#code#>
}