Abre la aplicación Maps programáticamente en iOS 6

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

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 acaba de abrir Mobile Safari a Google Maps. ¿Cómo puedo lograr el mismo comportamiento con iOS 6? ¿Cómo abro la aplicación Maps de forma programática y hago que apunte a una ubicación / dirección / búsqueda / lo que sea específica?

Esta es 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 mapItemForCurrentLocation con MKMapItem en la matriz en +openMapsWithItems:launchOptions: y establecer las opciones de inicio de la forma 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 statement else después de eso if . Tenga en cuenta que si invierte el orden de los elementos en la matriz openMapsWithItems: obtendrá instrucciones desde la coordenada hasta su ubicación actual. Probablemente pueda usarlo para obtener direcciones entre dos ubicaciones al pasar un MKMapItem construido en lugar del elemento del mapa de ubicación actual. No he intentado eso.

Finalmente, si tiene una dirección (como una cadena) a la que desea instrucciones, use el geocodificador para crear una MKPlacemark , mediante 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]; }]; } 

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

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

ACTUALIZACIÓN: Esto responde mi pregunta relacionada con el formato de URL. Pero la respuesta de Nevan King aquí (ver a continuación) es un excelente resumen de la API de Maps real.

La mejor forma 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.

Veo que encontró el “esquema” url 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 puede aprovechar: MKMapItem .

Dos métodos que te interesan:

  1. -openInMapsWithLaunchOptions: – llámalo a una instancia de MKMapItem para abrirlo en Maps.app
  2. + openMapsWithItems: launchOptions: – llámalo en la clase MKMapItem para abrir una matriz de instancias de MKMapItem.

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) } 

Me pareció molesto que al usar la configuración del enlace http://maps.apple.com?q= … se abra el navegador Safari primero en dispositivos más antiguos.

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

  1. haces 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 corro maps.google.com o maps.apple.com en el dispositivo (para las versiones del sistema operativo respectivamente ios 5 o ios 6).

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

  1. Si usa maps.google.com, se abrirá el mapa en safari por cada ios.
  2. Si usa maps.apple.com, entonces abrirá el mapa en la aplicación de mapa de ios 6 y también trabajará mejor con ios 5 y en ios 5 abrirá el mapa como es normal en safari.

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

Antes de ejecutar la url, elimine cualquier carácter especial de la url y reemplace los espacios por +. 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]; } 
 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

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!) } 

Puede difundir un poco de este código un poco. 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 lo restregué para usarlo en una URL.

Actualizado a Swift 4 según 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) }