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.