Abre mediante programación la aplicación Maps en iOS 6

159

Antes de iOS 6, abrir una URL como esta abriría la aplicación (Google) Maps:

NSURL *url = [NSURL URLWithString:@"http://maps.google.com/?q=New+York"];
[[UIApplication sharedApplication] openURL:url];

Ahora con la nueva implementación de Apple Maps, esto solo abre Mobile Safari a Google Maps. ¿Cómo puedo lograr el mismo comportamiento con iOS 6? ¿Cómo abro programáticamente la aplicación Mapas y hago que apunte a una ubicación / dirección / búsqueda / lo que sea específico?

Tom Hamming
fuente

Respuestas:

281

Aquí está la forma oficial de Apple:

// Check for iOS 6
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)]) 
{
    // Create an MKMapItem to pass to the Maps app
    CLLocationCoordinate2D coordinate = 
                CLLocationCoordinate2DMake(16.775, -3.009);
    MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate 
                                            addressDictionary:nil];
    MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
    [mapItem setName:@"My Place"];
    // Pass the map item to the Maps app
    [mapItem openInMapsWithLaunchOptions:nil];
}

Si desea obtener instrucciones para conducir o caminar a la ubicación, puede incluir un mapItemForCurrentLocationcon el MKMapItemen la matriz +openMapsWithItems:launchOptions:y configurar las opciones de inicio de manera adecuada.

// Check for iOS 6
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)]) 
{
    // Create an MKMapItem to pass to the Maps app
    CLLocationCoordinate2D coordinate = 
                CLLocationCoordinate2DMake(16.775, -3.009);
    MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate 
                                            addressDictionary:nil];
    MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
    [mapItem setName:@"My Place"];

    // Set the directions mode to "Walking"
    // Can use MKLaunchOptionsDirectionsModeDriving instead
    NSDictionary *launchOptions = @{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeWalking};
    // Get the "Current User Location" MKMapItem
    MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation];
    // Pass the current location and destination map items to the Maps app
    // Set the direction mode in the launchOptions dictionary
    [MKMapItem openMapsWithItems:@[currentLocationMapItem, mapItem] 
                    launchOptions:launchOptions];
}

Puede conservar su iOS 5 original y el código inferior en una elsedeclaración posterior if. Tenga en cuenta que si invierte el orden de los elementos en la openMapsWithItems:matriz, obtendrá indicaciones desde la coordenada hasta su ubicación actual. Probablemente podría usarlo para obtener direcciones entre dos ubicaciones pasando un elemento construido en MKMapItemlugar del mapa de ubicación actual. No he intentado eso.

Finalmente, si tiene una dirección (como una cadena) para la que desea direcciones, use el geocodificador para crear una MKPlacemark, a modo de CLPlacemark.

// Check for iOS 6
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)])
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder geocodeAddressString:@"Piccadilly Circus, London, UK" 
        completionHandler:^(NSArray *placemarks, NSError *error) {

        // Convert the CLPlacemark to an MKPlacemark
        // Note: There's no error checking for a failed geocode
        CLPlacemark *geocodedPlacemark = [placemarks objectAtIndex:0];
        MKPlacemark *placemark = [[MKPlacemark alloc]
                                  initWithCoordinate:geocodedPlacemark.location.coordinate
                                  addressDictionary:geocodedPlacemark.addressDictionary];

        // Create a map item for the geocoded address to pass to Maps app
        MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
        [mapItem setName:geocodedPlacemark.name];

        // Set the directions mode to "Driving"
        // Can use MKLaunchOptionsDirectionsModeWalking instead
        NSDictionary *launchOptions = @{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving};

        // Get the "Current User Location" MKMapItem
        MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation];

        // Pass the current location and destination map items to the Maps app
        // Set the direction mode in the launchOptions dictionary
        [MKMapItem openMapsWithItems:@[currentLocationMapItem, mapItem] launchOptions:launchOptions];

    }];
}
nevan king
fuente
El código funciona muy bien para iOS 6. Sin embargo, vale la pena mencionar que si la ruta que queremos es desde la ubicación actual del usuario a un destino, entonces no es necesario pasar currentLocationMapItem.
Philip007
1
El hecho de que haya utilizado las coordenadas de Tombouctou solo hace que la respuesta sea aún mejor :)
sachadso
+1 por mencionar que solo se trata de iOS 6 y que necesita un respaldo
Henrik Erlandsson
2
¿Cómo puedo navegar a mi aplicación actual desde aplicaciones de mapas?
Apple
1
¿Qué ubicación selecciono cuando abre la aplicación de mapas de Apple muestra alerta "no se pudieron encontrar direcciones entre estas ubicaciones ios 6" y luego no hace nada? Cualquier ayuda
NaXir
80

Encontré la respuesta a mi propia pregunta. Apple documenta su formato de URL de mapas aquí . Parece que esencialmente puedes reemplazarlo maps.google.comconmaps.apple.com .

Actualización: Resulta que lo mismo es cierto en MobileSafari en iOS 6; tocando un enlace para http://maps.apple.com/?q=...abrir la aplicación Mapas con esa búsqueda, de la misma manerahttp://maps.google.com/?q=... que en versiones anteriores. Esto funciona y está documentado en la página vinculada anteriormente.

ACTUALIZACIÓN: Esto responde a mi pregunta relacionada con el formato de URL. Pero la respuesta de nevan king aquí (ver más abajo) es un excelente resumen de la API de Maps real.

Tom Hamming
fuente
1
Interesante. Si abre un navegador en maps.apple.com, redirige a maps.google.com. ¿Me pregunto cuánto durará esto?
pir800
@ pir800 - En realidad, me preguntaba qué pasaría si tocas un enlace a maps.apple.com en Safari en iOS 6. Lo probé y va a Maps de la misma manera que en versiones anteriores de iOS cuando tocaste un enlace a maps.google.com. Creo que es una buena apuesta que estén redirigiendo a los mapas de Google para que los autores del sitio web puedan simplemente apuntar enlaces de mapas a maps.apple.com y hacer que funcione en iOS en Maps, pero que funcione normalmente en todos los demás clientes. ¡Pero me gustaría verificar eso de alguna manera antes de cambiar todos los enlaces de mi mapa para que apunten a maps.apple.com!
Tom Hamming
@ pir800: para mí, abrir maps.apple.com en un navegador me lleva a apple.com/ios/maps . Tal vez mi comentario anterior es una ilusión.
Tom Hamming
Me refiero a si intentas consultar una dirección o coordenada. Prueba maps.apple.com/?q=los angeles, ca. Puede abrirlo en su máquina de escritorio y lo reenviará a maps.google.com
pir800 el
¿Hay alguna manera de agregar el modo de tránsito a esa consulta? (caminar / conducir). No pude encontrar ninguna referencia a él en la web.
Lirik
41

La mejor manera de hacerlo es llamar al nuevo método iOS 6 en MKMapItem openInMapsWithLaunchOptions:launchOptions

Ejemplo:

CLLocationCoordinate2D endingCoord = CLLocationCoordinate2DMake(40.446947, -102.047607);
MKPlacemark *endLocation = [[MKPlacemark alloc] initWithCoordinate:endingCoord addressDictionary:nil];
MKMapItem *endingItem = [[MKMapItem alloc] initWithPlacemark:endLocation];

NSMutableDictionary *launchOptions = [[NSMutableDictionary alloc] init];
[launchOptions setObject:MKLaunchOptionsDirectionsModeDriving forKey:MKLaunchOptionsDirectionsModeKey];

[endingItem openInMapsWithLaunchOptions:launchOptions];

Esto iniciará la navegación para conducir desde la ubicación actual.

zvonicek
fuente
1
Bien, ¿cuál es la forma más fácil de obtener una instancia de MKMapItemcuando todo lo que tengo es una dirección? Esta API parece un poco complicada para ese caso de uso simple.
Tom Hamming
MKPlacemark * endLocation = [[MKPlacemark alloc] initWithCoordinate: nil addressDictionary: yourAdressDictHere]; usted puede entregar una dirección de Dictonary
mariusLAN
7

Veo que encontraste el "esquema" de la URL de maps.apple.com. Es una buena opción porque redirigirá automáticamente los dispositivos más antiguos a maps.google.com. Pero para iOS 6 hay una nueva clase que quizás quieras aprovechar: MKMapItem .

Dos métodos que le interesan:

  1. -openInMapsWithLaunchOptions: - llámelo en una instancia de MKMapItem para abrirlo en Maps.app
  2. + openMapsWithItems: launchOptions: - invocarlo en la clase MKMapItem para abrir una matriz de instancias MKMapItem.
Filip Radelic
fuente
Eso se ve útil. Pero también parece un poco más complicado de usar; tienes que hacerlo init MKMapItemcon un MKPlacemark, que obtienes al proporcionar un par de latitud / longitud y un diccionario de direcciones. Parece más simple simplemente abrir http://maps.apple.com/?q=1+infinite+loop+cupertino+ca. ¿Hay alguna ventaja de usar MKMapItemcuando todo lo que quieres hacer es mostrar una dirección en Maps?
Tom Hamming
No tiene que inicializar un MKMapItemsi aún no tiene una referencia a uno que le gustaría usar. Sólo tiene que utilizar el método de clase, +openMapsWithItems:launchOptions:en la MKMapItemque hacer la misma cosa.
Mark Adams
@MarkAdams ese método de clase toma una serie de instancias de clase, por lo que sí necesita tener al menos una inicializada.
Filip Radelic
Entonces, en una situación en la que tengo que abrir coordenadas GPS, pero no hay dirección, uso la MKMapItemAPI y deja caer un punto en el mapa etiquetado como "Ubicación desconocida". ¿Hay alguna manera de hacer que muestre un nombre para la ubicación? No veo ninguna clave para esto en las opciones para el diccionario de direcciones ...
Tom Hamming
55
@ Mr.Jefferson Establezca la propiedad de nombre de MKMapItem
mate
5

Aquí hay una clase que usa la solución de nevan king completada en Swift:

class func openMapWithCoordinates(theLon:String, theLat:String){

            var coordinate = CLLocationCoordinate2DMake(CLLocationDegrees(theLon), CLLocationDegrees(theLat))

            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)
}
PJeremyMalouf
fuente
4

Me pareció molesto que usando el http://maps.apple.com?q= configuración de enlace ... abra primero el navegador safari en dispositivos más antiguos.

Entonces, para un dispositivo iOS 5 que abre su aplicación con una referencia a maps.apple.com, los pasos son los siguientes:

  1. hace clic en algo en la aplicación y se refiere a la URL de maps.apple.com
  2. safari abre el enlace
  3. el servidor de maps.apple.com redirige a la URL de maps.google.com
  4. la url de maps.google.com se interpreta y abre la aplicación google Maps.

Creo que los pasos 2 y 3 (muy obvios y confusos) son molestos para los usuarios. Por lo tanto, verifico la versión del sistema operativo y ejecuto maps.google.com o maps.apple.com en el dispositivo (para las versiones del sistema operativo iOS 5 o iOS 6).

EeKay
fuente
Eso es lo que estoy haciendo también. Parece el mejor enfoque.
Tom Hamming
3

Mi investigación sobre este tema me llevó a las siguientes conclusiones:

  1. Si usa maps.google.com, se abrirá el mapa en safari para cada ios.
  2. Si usa maps.apple.com, abrirá el mapa en la aplicación de mapas de ios 6 y también funcionará mejor con ios 5 y en ios 5 abrirá el mapa de manera normal en un safari.
Miel jain
fuente
3

Si desea abrir Google Maps en su lugar (u ofrecerlo como una opción secundaria), puede usar los esquemas comgooglemaps://y comgooglemaps-x-callback://URL documentados aquí .

Johan Kool
fuente
3

Antes de iniciar url, elimine cualquier carácter especial de la url y reemplace los espacios con +. Esto te ahorrará algunos dolores de cabeza:

    NSString *mapURLStr = [NSString stringWithFormat: @"http://maps.apple.com/?q=%@",@"Limmattalstrasse 170, 8049 Zürich"];

    mapURLStr = [mapURLStr stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    NSURL *url = [NSURL URLWithString:[mapURLStr stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
    if ([[UIApplication sharedApplication] canOpenURL:url]){
            [[UIApplication sharedApplication] openURL:url];
        }
Javier Calatrava Llavería
fuente
2
NSString *address = [NSString stringWithFormat:@"%@ %@ %@ %@"
                             ,[dataDictionary objectForKey:@"practice_address"]
                             ,[dataDictionary objectForKey:@"practice_city"]
                             ,[dataDictionary objectForKey:@"practice_state"]
                             ,[dataDictionary objectForKey:@"practice_zipcode"]];


        NSString *mapAddress = [@"http://maps.apple.com/?q=" stringByAppendingString:[address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

        NSLog(@"Map Address %@",mapAddress);

        [objSpineCustomProtocol setUserDefaults:mapAddress :@"webSiteToLoad"];

        [self performSegueWithIdentifier: @"provider_to_web_loader_segue" sender: self];

// VKJ

Vinod Joshi
fuente
2

Actualizado a Swift 4 basado en la respuesta de @ PJeremyMalouf:

private func navigateUsingAppleMaps(to coords:CLLocation, locationName: String? = nil) {
    let placemark = MKPlacemark(coordinate: coords.coordinate, addressDictionary:nil)
    let mapItem = MKMapItem(placemark: placemark)
    mapItem.name = locationName
    let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
    let currentLocationMapItem = MKMapItem.forCurrentLocation()

    MKMapItem.openMaps(with: [currentLocationMapItem, mapItem], launchOptions: launchOptions)
}
Chris Prince
fuente
1

No usar mapas, solo usar programáticamente una acción UiButton, esto funcionó muy bien para mí.

// Button triggers the map to be presented.

@IBAction func toMapButton(sender: AnyObject) {

//Empty container for the value

var addressToLinkTo = ""

//Fill the container with an address

self.addressToLinkTo = "http://maps.apple.com/?q=111 Some place drive, Oak Ridge TN 37830"

self.addressToLinkTo = self.addressToLinkTo.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!

let url = NSURL(string: self.addressToLinkTo)
UIApplication.sharedApplication().openURL(url!)

                }

Podrías difundir un poco este código. Por ejemplo, puse la variable como una variable de nivel de clase, hice que otra función la llenara y luego, cuando presioné el botón, simplemente tomé lo que estaba en la variable y la borré para usarla en una URL.

Christopher Wade Cantley
fuente