Display route on map in Swift

后端 未结 2 1952
我在风中等你
我在风中等你 2021-02-06 14:21

I am trying to draw the route between two points on Apple map (Swift code). The following structure is used to store the coordinates

struct GeoLocation {
    va         


        
相关标签:
2条回答
  • 2021-02-06 14:52

    Swift 3 and reusable conversion of Lyndsey Scott's 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)
    
                        }
    
                    }
    
                }
    
            }
    
        }
    
    }
    

    Usage:

    Route.getRouteFor(source: CLLocationCoordinate2D, destination: CLLocationCoordinate2D) { (MKRoute?, String?) in
           <#code#>
    }
    
    0 讨论(0)
  • 2021-02-06 14:54

    You actually have to fetch the route from Apple's maps' server using calculateDirectionsWithCompletionHandler.

    First create the relevant MKMapItems for both the source and destination, ex:

    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 fetch the 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 retrieving the MKRoute, you can add the polyline to the map like so:

    mapView.addOverlay(route.polyline, level: MKOverlayLevel.AboveRoads)
    
    0 讨论(0)
提交回复
热议问题