Show route on the map from Swift

I am trying to route between two points on an Apple map (Swift code). To store coordinates

The following structure is used:
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 

In a custom class, I get the coordinates of the points on the map.

 var coordinates = self.foundLocations.map{$0.coordinate} 

Then I draw a route on a map

 self.polyline = MKPolyline(coordinates: &coordinates, count: coordinates.count) self.mapView.addOverlay(self.polyline, level: MKOverlayLevel.AboveRoads) 

To draw a route, I use the following method from 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 } 

Instead of actually plotting the route along the roads, I get only a straight line between two points. How can I display the actual route?

+5
source share
2 answers

You really need to get the route from the Apple maps server using calculateDirectionsWithCompletionHandler .

First create the appropriate MKMapItem for the source and destination, for example:

 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) } } }) 

(Repeat for destination.)

Then select MKRoute , ex:

 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 } }) 

Then after extracting MKRoute you can add a polyline to the map as follows:

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

Swift 3 and reusing Lyndsey Scott answer:

 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) } } } } } } 

Using:

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

Source: https://habr.com/ru/post/1214181/


All Articles