132

I have latitude and longitude that I want to open into my map application. I tried this code from HERE.

    func goToMap(){

    var lat1 : NSString = self.venueLat
    var lng1 : NSString = self.venueLng

    var latitude:CLLocationDegrees =  lat1.doubleValue
    var longitude:CLLocationDegrees =  lng1.doubleValue

    var coordinate = CLLocationCoordinate2DMake(latitude, longitude)

    var placemark : MKPlacemark = MKPlacemark(coordinate: coordinate, addressDictionary:nil)

    var mapItem:MKMapItem = MKMapItem(placemark: placemark)

    mapItem.name = "Target location"

    let launchOptions:NSDictionary = NSDictionary(object: MKLaunchOptionsDirectionsModeDriving, forKey: MKLaunchOptionsDirectionsModeKey)

    var currentLocationMapItem:MKMapItem = MKMapItem.mapItemForCurrentLocation()

    MKMapItem.openMapsWithItems([currentLocationMapItem, mapItem], launchOptions: launchOptions)

}

This function successfully open maps but it doesn't show any pin. Also it shows user location which I don't want. I only want a pin on the map for the provided latitude and longitude.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Dharmesh Kheni
  • 71,228
  • 33
  • 160
  • 165
  • 2
    This code is intended to show driving directions from the user location to the target. To just show a single target, use MKLaunchOptionsMapCenterKey and a single map item. See http://stackoverflow.com/questions/28427557/openinmapswithlaunchoptions-not-working. –  Feb 19 '15 at 13:13

11 Answers11

186

This code is working fine for me.

func openMapForPlace() {
    
    let lat1 : NSString = self.venueLat
    let lng1 : NSString = self.venueLng
    
    let latitude:CLLocationDegrees =  lat1.doubleValue
    let longitude:CLLocationDegrees =  lng1.doubleValue
    
    let regionDistance:CLLocationDistance = 10000
    let coordinates = CLLocationCoordinate2DMake(latitude, 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 = "\(self.venueName)"
    mapItem.openInMapsWithLaunchOptions(options)
    
}

For swift 3.0:

import UIKit
import MapKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        openMapForPlace()
    }
    
    func openMapForPlace() {
        
        let latitude: CLLocationDegrees = 37.2
        let longitude: CLLocationDegrees = 22.9
        
        let regionDistance:CLLocationDistance = 10000
        let coordinates = CLLocationCoordinate2DMake(latitude, 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 = "Place Name"
        mapItem.openInMaps(launchOptions: options)
    }
}

Swift 5:

let latitude: CLLocationDegrees = Double(K.latitude)!
let longitude: CLLocationDegrees = Double(K.longitude)!
let regionDistance:CLLocationDistance = 10000
let coordinates = CLLocationCoordinate2DMake(latitude, longitude)
let regionSpan = MKCoordinateRegion(center: coordinates, latitudinalMeters: regionDistance, longitudinalMeters: 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 = K.companyName
mapItem.openInMaps(launchOptions: options)
frankenapps
  • 5,800
  • 6
  • 28
  • 69
Dharmesh Kheni
  • 71,228
  • 33
  • 160
  • 165
  • Can you confirm that the MKLaunchOptionsMapSpanKey option has the desired effect? No matter what value I use for CLLocationDistance, the map is zoomed in pretty closely. – stone May 28 '15 at 05:52
  • 2
    It seems that the `MKLaunchOptionsMapSpanKey` is ignored when one or more `MKMapItem` are added to the map: http://stackoverflow.com/a/32484331/422288 – Eneko Alonso Sep 09 '15 at 16:07
  • 5
    Don't forget: import MapKit – jobima Feb 17 '16 at 11:42
  • 11
    Just wanted to point out that it's "latitude" and "longitude" not "latitute" and "longitute" although "tute" is funnier – Chris Aug 16 '16 at 12:25
  • 2
    if the user have removed the maps application that how can we check on that case??? – Amrit Tiwari Feb 09 '17 at 06:11
  • `import MapKit` and `import CoreLocation` too! – kbunarjo Dec 07 '17 at 08:45
  • @kbunarjo, why do we require to import `CoreLocation`? – Hemang Apr 11 '18 at 07:07
  • @AmritTiwari Good question.. A very clear explanation to this is given here: https://stackoverflow.com/questions/39603120/how-to-check-if-apple-maps-is-installed – kinza Aug 09 '18 at 12:17
  • i am trying to implement lets hope for the best. – Abu Ul Hassan Sep 14 '18 at 06:07
  • It looks like will work like a charm and even it says "Directions" but once I tap there it says, directions not available. AND my country is on the supported list. – Marlhex Nov 08 '19 at 03:45
80

If you just want to give the user driving directions, here's the latest Swift syntax in its simplest form:

let coordinate = CLLocationCoordinate2DMake(theLatitude,theLongitude)
let mapItem = MKMapItem(placemark: MKPlacemark(coordinate: coordinate, addressDictionary:nil))
mapItem.name = "Target location"
mapItem.openInMaps(launchOptions: [MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving])
Francesco D.M.
  • 2,129
  • 20
  • 27
Joe C
  • 2,728
  • 4
  • 30
  • 38
  • 1
    This worked well for me, except that the key and value are reversed in the launch options. Should be `mapItem.openInMapsWithLaunchOptions([MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving])` – Keith Jun 02 '16 at 13:33
  • 1
    Make sure to add import MapKit to top of the file to resolve errors. – Joseph Astrahan Nov 03 '16 at 03:29
  • 2
    Also in swift 3 the last line is now... mapItem.openInMaps(launchOptions: [MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving]) – Joseph Astrahan Nov 03 '16 at 03:29
55

You could call class function of MKMapItem passing items there, it uses only first and last for source / destination appropriately, if you want pass more than two items.

Swift 5, 4

let source = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: lat, longitude: lng)))
source.name = "Source"
        
let destination = MKMapItem(placemark: MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: lat, longitude: lng)))
destination.name = "Destination"
        
MKMapItem.openMaps(
  with: [source, destination], 
  launchOptions: [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
)

or using extension:

extension MKMapItem {
  convenience init(coordinate: CLLocationCoordinate2D, name: String) {
    self.init(placemark: .init(coordinate: coordinate))
    self.name = name
  }
}

let source = MKMapItem(coordinate: .init(latitude: lat, longitude: lng), name: "Source")
let destination = MKMapItem(coordinate: .init(latitude: lat, longitude: lng), name: "Destination")

MKMapItem.openMaps(
  with: [source, destination], 
  launchOptions: [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
)
dimpiax
  • 12,093
  • 5
  • 62
  • 45
  • hi dimpiax! Thanks for your answer, didn't test it but seems pretty ok. Is it possible to send several waypoints? How!? Can you please help me. – Frade Jul 31 '20 at 10:28
  • @Frade hey, with MapKit you cannot, see: https://developer.apple.com/documentation/mapkit/mkmapitem/1452207-openmaps But you can achieve it using Google Maps. – dimpiax Jul 31 '20 at 10:48
  • Yes, I saw it, minutes after. Thanks – Frade Aug 17 '20 at 17:54
39

The MKMapItem approach above works great if you want granular control over the information that is displayed in Maps.

Otherwise, the code below works great as well, :

// Open and show coordinate
let url = "http://maps.apple.com/maps?saddr=\(coord.latitude),\(coord.longitude)"
UIApplication.shared.openURL(URL(string:url)!)

// Navigate from one coordinate to another
let url = "http://maps.apple.com/maps?saddr=\(from.latitude),\(from.longitude)&daddr=\(to.latitude),\(to.longitude)"
UIApplication.shared.openURL(URL(string:url)!)

However, the code above does not let you to send in a custom name of the place. Instead, it will show the address.

The code above also lets you navigate from any source coordinate, which I don't know if you can do with the MKMapItem approach.

Daniel Saidi
  • 6,079
  • 4
  • 27
  • 29
13

This works as a charm for me

let coordinate = CLLocationCoordinate2DMake(theLatitude, theLongitude)
let region = MKCoordinateRegionMake(coordinate, MKCoordinateSpanMake(0.01, 0.02))
let placemark = MKPlacemark(coordinate: coordinate, addressDictionary: nil)
let mapItem = MKMapItem(placemark: placemark)
let options = [
    MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: region.center),
    MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: region.span)]
mapItem.name = theLocationName
mapItem.openInMaps(launchOptions: options)
Wayne Huang
  • 495
  • 6
  • 17
4

You can use below code to show PIN on lat, long in to Apple map.

let coordinates = CLLocationCoordinate2DMake(-37.848854,144.990295)

let regionSpan =   MKCoordinateRegionMakeWithDistance(coordinates, 1000, 1000)

let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)

let mapItem = MKMapItem(placemark: placemark)

mapItem.name = “Desired place”

mapItem.openInMaps(launchOptions:[
MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center)
] as [String : Any])
Malik 007
  • 43
  • 6
4

If what you want is something simple without importing any framework you can just create a URL: https://maps.apple.com/?ll=\(latitude),\(longitude)

Is similar to @saniel-saidi response but this one opens just the map with location sent, not the navigation thing

rgkobashi
  • 2,551
  • 19
  • 25
3

Update to the practical Daniel Saidi answer. This example is for telling only the destination coordinates. Maps will get as origin the user current position.

let url = URL(string: "http://maps.apple.com/maps?saddr=&daddr=\(lat),\(lon)")
UIApplication.shared.open(url!)

Nicola Mingotti
  • 860
  • 6
  • 15
2

I know all answers are complete but here I got an answer which is easier to copy paste & also gives the user options to routing with Apple Maps, Google Map & Waze.

Working with Swift 5+

https://stackoverflow.com/a/60930491/6449292

Might help someone...

Ahmadreza
  • 6,950
  • 5
  • 50
  • 69
2

Swift 5 Solution:

Open Apple Map OR Google Map Programmatically

  let actionSheet = UIAlertController(title: "Open Location", message: "Choose an app to open direction", preferredStyle: .actionSheet)
                actionSheet.addAction(UIAlertAction(title: "Google Maps", style: .default, handler: { _ in
                    // Pass the coordinate inside this URL
                    self.openGoogleMap()
                }))
                actionSheet.addAction(UIAlertAction(title: "Apple Maps", style: .default, handler: { _ in
                    // Pass the coordinate that you want here
                    self.openAppleMap()
                }))
                actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
                self.present(actionSheet, animated: true, completion: nil)

//Function defination here


func openAppleMap(){
        guard let lat = bookingData.gpsLatitude, let latDouble =  Double(lat) else {return }
        guard let long = bookingData.gpsLongitude, let longDouble =  Double(long) else {return }
        
        let coordinate = CLLocationCoordinate2DMake(latDouble,longDouble)
                    let mapItem = MKMapItem(placemark: MKPlacemark(coordinate: coordinate, addressDictionary: nil))
                    mapItem.name = "Destination"
                    mapItem.openInMaps(launchOptions: [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving])
    }
    


func openGoogleMap() {
            guard let lat = bookingData.gpsLatitude, let latDouble =  Double(lat) else {return }
            guard let long = bookingData.gpsLongitude, let longDouble =  Double(long) else {return }
            if (UIApplication.shared.canOpenURL(URL(string:"comgooglemaps://")!)) {  //if phone has an app
                
                if let url = URL(string: "comgooglemaps-x-callback://?saddr=&daddr=\(latDouble),\(longDouble)&directionsmode=driving") {
                    UIApplication.shared.open(url, options: [:])
                }}
            else {
                //Open in browser
                if let urlDestination = URL.init(string: "https://www.google.co.in/maps/dir/?saddr=&daddr=\(latDouble),\(longDouble)&directionsmode=driving") {
                    UIApplication.shared.open(urlDestination)
                }
            }
        }
    

Don't forget to write this in info.plist

<key>LSApplicationQueriesSchemes</key>
    <array>
    <string>comgooglemaps</string>
    <string>comgooglemaps-x-callback</string>
    </array>
Sourabh Sharma
  • 8,222
  • 5
  • 68
  • 78
1

The simplest way to open the Apple Maps app and show a pin on the custom location with a custom title is that:

let url = URL(string: "maps://?q=Title&ll=\(latitude),\(longitude)")!
if UIApplication.shared.canOpenURL(url) {
    UIApplication.shared.open(url)
}

Look here for more options: https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html

Nikaaner
  • 1,022
  • 16
  • 19