1
votes

Trying to get direction to selected annotation on the map from the current location of the User but not sure how to catch selected annotation(when user selecting one of them) and show direction.Checked different topics on the Stack but there is not a lot of fresh information about how catch selected annotation and show direction for user location.Please advise.

import UIKit
import MapKit
import CoreLocation

class NavigationVC: UIViewController {

@IBOutlet weak var mapView: MKMapView!
let manager = CLLocationManager()
let request = MKLocalSearchRequest()

override func viewDidLoad() {
    super.viewDidLoad()

    manager.delegate = self
    manager.desiredAccuracy =   kCLLocationAccuracyBest
    manager.requestWhenInUseAuthorization()
    manager.startUpdatingLocation()


  }


 }
 //MARK: CONFIGURATION OF MAPVIEW

 extension NavigationVC: CLLocationManagerDelegate {

  func locationManager(_ manager: CLLocationManager, didUpdateLocations 
    locations: [CLLocation]) {
    let location = locations[0]
    let span: MKCoordinateSpan = MKCoordinateSpanMake(0.1, 0.1 )
    let userLocation:CLLocationCoordinate2D = 
    CLLocationCoordinate2DMake(location.coordinate.latitude, 
    location.coordinate.longitude)
    let region: MKCoordinateRegion = 
    MKCoordinateRegionMake(userLocation, span)
    mapView.setRegion(region, animated: true)
    self.mapView.showsUserLocation = true

    request.naturalLanguageQuery = "Currency exchange"
    request.region = mapView.region
    let activeSearch = MKLocalSearch(request: request)
    activeSearch.start { (response, error) in

        guard let response = response else {
            return
        }

        for item in response.mapItems {
            let annotation = MKPointAnnotation()
            annotation.coordinate = item.placemark.coordinate
            annotation.title = item.name

            DispatchQueue.main.async {
                self.mapView.addAnnotation(annotation)
            }
        }
    }


  }

  func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> 
 MKOverlayRenderer {
    let polylineRenderer = MKPolylineRenderer(overlay: overlay)
    polylineRenderer.strokeColor = UIColor.blue
    polylineRenderer.fillColor = UIColor.red
    polylineRenderer.lineWidth = 2
    return polylineRenderer


  }

}
2

2 Answers

0
votes

To get the path on the map from your position to the annotation follow this code:

    annotation = MKPointAnnotation()
    annotation.coordinate = CLLocationCoordinate2D(latitude: CLLocationDegrees(lat),longitude: CLLocationDegrees(lon))
    self.map?.addAnnotation(annotation)


    var route : MKRoute? = nil

    DispatchQueue.global(qos: .userInitiated).async { [weak self] in
        let directionRequest = MKDirectionsRequest()
        directionRequest.source = MKMapItem.forCurrentLocation();
        directionRequest.destination = MKMapItem(placemark: MKPlacemark(coordinate:(self?.annotation.coordinate)!))
        directionRequest.transportType = .automobile
        let directions = MKDirections(request: directionRequest)

        directions.calculate {
            (response, error) -> Void in
            guard let response = response else {
                if let error = error {
                    print("Error: \(error)")
                }
                return
            }

            route = response.routes[0]
            if let percorso = route{
                DispatchQueue.main.async { [weak self] in
                    self?.map?.add((percorso.polyline), level: MKOverlayLevel.aboveRoads)
                }
            }
        }
    }

You have only to select the correct annotation, maybe try to register a touch listener on the annotation.

0
votes

Use didSelect delegate method.

e.g.

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    guard let annotation = view.annotation else {
        return
    }

    let directionRequest = MKDirectionsRequest()
    directionRequest.source = MKMapItem.forCurrentLocation()
    directionRequest.destination = MKMapItem(placemark: MKPlacemark(coordinate: annotation.coordinate))
    directionRequest.transportType = .automobile
    let directions = MKDirections(request: directionRequest)

    directions.calculate {
        (response, error) -> Void in
        guard let response = response else {
            if let error = error {
                print("Error: \(error)")
            }
            return
        }

        if !response.routes.isEmpty {
            let route = response.routes[0]
            DispatchQueue.main.async { [weak self] in
                self?.mapView.add(route.polyline)
            }
        }
    }
}

Don't forget guard to prevent crash.

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) ->
    MKOverlayRenderer {
        guard overlay is MKPolyline else {
            return MKPolylineRenderer()
        }
    ...
}

Good luck!