Hello, Im trying to implement directions (navigation) from my app. All I want to do is to open map app (Google Maps or Apple Maps) with ready to go directions after user click button - in my case leftCalloutAccessoryView
called leftButton
. I've been trying some options, but without a good result. Here is my code:
func findPlace(_ places: [Place]) { for place in places { let annotations = MKPointAnnotation() annotations.title = place.name annotations.subtitle = place.description annotations.coordinate = CLLocationCoordinate2D(latitude: place.lattitude, longitude: place.longtitude) mapView.addAnnotation(annotations) } } func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { guard !(annotation is MKUserLocation) else { return nil } mapView.delegate = self let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: String(annotation.hash)) let identifier = "identifier" annotationView.canShowCallout = true guard let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier, for: annotation) as? MKMarkerAnnotationView else { return nil } let rightButton = UIButton(type: .detailDisclosure) rightButton.tag = annotation.hash annotationView.canShowCallout = true annotationView.rightCalloutAccessoryView = rightButton let leftButton = UIButton(frame: CGRect( origin: CGPoint.zero, size: CGSize(width: 25, height: 25))) leftButton.setBackgroundImage(#imageLiteral(resourceName: "nav"), for: .normal) annotationView.leftCalloutAccessoryView = leftButton leftButton.addTarget(self, action: #selector(didClickDetailDisclosureNavigation(button:)), for: .touchUpInside) @objc func didClickDetailDisclosureNavigation(button: UIButton) { let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving] ????.openInMaps(launchOptions: launchOptions) //Here I've tried some solutions like `annotations.openInMaps(launchOptions: launchOptions)`- but it does not make sense. }
I would like to do this like here: https://www.raywenderlich.com/7738344-mapkit-tutorial-getting-started
If you want to do things as shown in the tutorial, you need to instantiate a MKMapItem
as instructed.
As you are using MKPointAnnotation
, you can define an extension like this:
extension MKPointAnnotation { var mapItem: MKMapItem { let placemark = MKPlacemark(coordinate: self.coordinate) return MKMapItem(placemark: placemark) } }
To utilized this extension, you may need to pass the right annotation
(which needs to be an MKPointAnnotation
) to didClickDetailDisclosureNavigation(button:)
.
Which may be hard using a usual UIButton
. You should better define your own button type which can hold an annotation
.
Not too complex:
class AnnotationButton: UIButton { var annotation: MKPointAnnotation? }
(Please do not put the extension and the class definition inside some other type. They need to be toplevel definitions.)
Your code would become something like this:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { guard !(annotation is MKUserLocation) else { return nil } //mapView.delegate = self //->Move this to `viewDidLoad()` //This `annotationView` will be shadowed by the following `annotationView`, not used. //let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: String(annotation.hash)) let identifier = "identifier" //annotationView.canShowCallout = true guard let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier, for: annotation) as? MKMarkerAnnotationView else { return nil } //... let leftButton = AnnotationButton(frame: CGRect( //<- origin: .zero, size: CGSize(width: 25, height: 25))) leftButton.setBackgroundImage(#imageLiteral(resourceName: "nav"), for: .normal) annotationView.leftCalloutAccessoryView = leftButton leftButton.addTarget(self, action: #selector(didClickDetailDisclosureNavigation(button:)), for: .touchUpInside) //↓↓ if let pointAnnotation = annotation as? MKPointAnnotation { leftButton.annotation = pointAnnotation } //... return annotationView } @objc func didClickDetailDisclosureNavigation(button: AnnotationButton) { //<- let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving] //↓↓ if let mapItem = button.annotation?.mapItem { mapItem.openInMaps(launchOptions: launchOptions) } }
I haven't tried it myself (as you are not showing many parts of your code), but please try.