I've implemented it in Swift 4
Define an enum for all the navigation apps you want to open.
enum NavigationApps: String {
case appleMaps = "Maps"
case googleMaps = "Google Maps"
case hereWeGo = "HERE WeGo"
}
Following method takes latitude and longitude parameters in location tuple and opens action sheet with options of all the maps present in enum above and installed on user device. installedNavigationApps
is an array of dictionary (key/value pairs) where keys are from NavigationApps
enum and values are their respective URL schemes.
All you need to do is to mention all navigation apps in NavigationApps
enum, URL schemes in installedNavigationApps
array of dictionary, and handle app launch for each navigation app in UIAlertAction
handler.
import MapKit
extension UIViewController {
// MARK: - Map Navigation
func openMapForLocation(location: (latitude: CLLocationDegrees, longitude: CLLocationDegrees)) {
let installedNavigationApps : [[String:String]] = [[NavigationApps.appleMaps.rawValue:""], [NavigationApps.googleMaps.rawValue:"comgooglemaps://"], [NavigationApps.hereWeGo.rawValue:"here-route://"]]
var alertAction: UIAlertAction?
let alert = UIAlertController(title: "Select Navigation App", message: "Open in", preferredStyle: .actionSheet)
for app in installedNavigationApps {
let appName = app.keys.first
if (appName == NavigationApps.appleMaps.rawValue ||
appName == NavigationApps.googleMaps.rawValue || UIApplication.shared.canOpenURL(URL(string:app[appName!]!)!))
{
alertAction = UIAlertAction(title: appName, style: .default, handler: { (action) in
switch appName {
case NavigationApps.appleMaps.rawValue?:
let regionDistance:CLLocationDistance = 10000
let coordinates = CLLocationCoordinate2DMake(location.latitude, location.longitude)
let regionSpan = MKCoordinateRegionMakeWithDistance(coordinates, regionDistance, regionDistance)
let options = [
MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
]
let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = "KIZAD"
mapItem.openInMaps(launchOptions: options)
break
case NavigationApps.googleMaps.rawValue?:
if UIApplication.shared.canOpenURL(URL(string:app[appName!]!)!) {
//open in Google Maps application
UIApplication.shared.open(URL(string:
"comgooglemaps://?saddr=&daddr=\(location.latitude),\(location.longitude)&directionsmode=driving")! as URL, options: [:], completionHandler: nil)
} else {
//open in Browser
let string = "https://maps.google.com/?q=@\(location.latitude),\(location.longitude)"
UIApplication.shared.open(URL(string: string)!)
}
break
case NavigationApps.hereWeGo.rawValue?:
UIApplication.shared.open(URL(string:
"here-route://mylocation/\(location.latitude),\(location.longitude)?ref=KIZAD&m=d")! as URL, options: [:], completionHandler: nil)
break
default:
break
}
})
alert.addAction(alertAction!)
}
else
{
print("Can't open URL scheme")
}
}
alertAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(alertAction!)
self.present(alert, animated: true, completion: nil)
}
}
IMPORTANT:
Do NOT forget to add URL scheme of all third party navigation apps in info.plist. For instance:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>comgooglemaps</string>
<string>here-route</string>
</array>