Apri a livello di programmazione l'app Mappe in iOS 6


159

Prima di iOS 6, aprendo un URL come questo si apriva l'app (Google) Maps:

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

Ora con la nuova implementazione di Apple Maps, questo apre Mobile Safari a Google Maps. Come posso ottenere lo stesso comportamento con iOS 6? Come posso aprire a livello di programmazione l'app Mappe e farla puntare a una posizione / indirizzo / ricerca / qualunque cosa specifici?

Risposte:


281

Ecco il modo Apple ufficiale:

// 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];
}

Se si desidera ottenere le istruzioni di guida o di camminata verso la posizione, è possibile includere un mapItemForCurrentLocationcon MKMapIteml'array in +openMapsWithItems:launchOptions:e impostare le opzioni di avvio in modo appropriato.

// 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];
}

Successivamente puoi conservare il tuo codice iOS 5 originale e un codice inferiore in una elsedichiarazione if. Notare che se si inverte l'ordine degli elementi openMapsWithItems:nell'array, si otterranno le indicazioni dalle coordinate alla posizione corrente. Probabilmente potresti usarlo per ottenere indicazioni stradali tra due posizioni qualsiasi passando un MKMapItemelemento della mappa della posizione costruito anziché quello corrente. Non ci ho provato.

Infine, se si dispone di un indirizzo (come stringa) a cui si desidera ottenere indicazioni stradali, utilizzare il geocoder per crearne uno MKPlacemark, tramite 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];

    }];
}

Il codice funziona benissimo per iOS 6. Vale la pena ricordare, tuttavia, se il percorso che vogliamo è dalla posizione dell'utente corrente a una destinazione, non è necessario passare currentLocationMapItem.
Philip007,

1
Il fatto che tu abbia usato le coordinate di Tombouctou rende la risposta ancora migliore :)
sachadso

+1 per menzionare che è solo iOS 6 e che è necessario un fallback
Henrik Erlandsson

2
come posso navigare alla mia attuale applicazione dalle app della mappa?
Apple,

1
Quale posizione ho selezionato quando apre l'app Apple Maps, mostra l'avviso "Impossibile trovare indicazioni stradali tra queste posizioni iOS 6" e quindi non fa nulla? Qualsiasi aiuto
NaXir

80

Ho trovato la risposta alla mia domanda. Documenti di Apple le sue mappe formato URL qui . Sembra che puoi essenzialmente sostituirlo maps.google.comcon maps.apple.com.

Aggiornamento: si scopre che lo stesso vale in MobileSafari su iOS 6; toccando un link per http://maps.apple.com/?q=...aprire l'app Maps con quella ricerca, come http://maps.google.com/?q=...nelle versioni precedenti. Funziona ed è documentato nella pagina collegata sopra.

AGGIORNAMENTO: Questo risponde alla mia domanda relativa al formato URL. Ma la risposta di nevan king qui (vedi sotto) è un eccellente riassunto dell'API di Maps attuale.


1
Interessante. Se apri un browser su maps.apple.com reindirizza a maps.google.com. Mi chiedo quanto durerà?
pir800,

@ pir800 - In realtà mi stavo solo chiedendo cosa sarebbe successo se toccassi un link a maps.apple.com in Safari su iOS 6. L'ho provato e va su Maps allo stesso modo delle versioni precedenti di iOS quando hai toccato un link a maps.google.com. Penso che sia una buona scommessa che stanno reindirizzando a Google Maps in modo che gli autori del sito Web possano semplicemente puntare i collegamenti delle mappe a maps.apple.com e farlo funzionare su iOS in Maps ma normalmente su tutti gli altri client. Ma vorrei verificarlo in qualche modo prima di cambiare tutti i miei collegamenti delle mappe per puntare a maps.apple.com!
Tom Hamming,

@ pir800 - per me, l'apertura di maps.apple.com in un browser mi porta a apple.com/ios/maps . Forse il mio commento precedente è un pio desiderio.
Tom Hamming,

Intendevo dire se provi a cercare un indirizzo o una coordinata. Prova maps.apple.com/?q=los angeles, ca. Puoi aprirlo sul tuo computer desktop e verrà inoltrato a maps.google.com
pir800,

C'è un modo per aggiungere la modalità di transito a quella query? (camminare / guidare). non è stato possibile trovare alcun riferimento ad esso sul Web.
Lirik,

41

Il modo migliore per farlo è chiamare il nuovo metodo iOS 6 MKMapItem openInMapsWithLaunchOptions:launchOptions

Esempio:

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];

Ciò avvierà la navigazione per guidare dalla posizione corrente.


1
OK, quindi qual è il modo più semplice per ottenere un'istanza di MKMapItemquando tutto ciò che ho è un indirizzo? Questa API sembra un po 'complicata per quel semplice caso d'uso.
Tom Hamming,

MKPlacemark * endLocation = [[allocazione MKPlacemark] initWithCoordinate: nil addressDictionary: yourAdressDictHere]; puoi consegnare un indirizzo Dictonary in
mariusLAN,

7

Vedo che hai trovato lo "schema" dell'URL maps.apple.com. È una buona scelta perché reindirizzerà automaticamente i dispositivi più vecchi su maps.google.com. Ma per iOS 6 c'è una nuova classe che potresti voler sfruttare: MKMapItem .

Due metodi che ti interessano:

  1. -openInMapsWithLaunchOptions: - chiamalo su un'istanza MKMapItem per aprirlo in Maps.app
  2. + openMapsWithItems: launchOptions: - chiamalo sulla classe MKMapItem per aprire un array di istanze MKMapItem.

Sembra utile. Ma sembra anche un po 'più complicato da usare; devi init MKMapItemcon un MKPlacemark, che ottieni fornendo una coppia latitudine / longitudine e un dizionario di indirizzi. Sembra più semplice da aprire http://maps.apple.com/?q=1+infinite+loop+cupertino+ca. C'è un vantaggio nell'utilizzare MKMapItemquando tutto ciò che vuoi fare è mostrare un indirizzo in Maps?
Tom Hamming,

Non è necessario inizializzare un MKMapItemse non si dispone già di un riferimento a quello che si desidera utilizzare. Basta usare il metodo della classe, +openMapsWithItems:launchOptions:su MKMapItemper fare la stessa cosa.
Mark Adams,

@MarkAdams quel metodo di classe accetta una serie di istanze di classe, quindi sì, deve averne almeno uno inizializzato.
Filip Radelic,

Quindi, in una situazione in cui ho le coordinate GPS da aprire, ma nessun indirizzo, utilizzo l' MKMapItemAPI e rilascia un punto sulla mappa etichettato "Posizione sconosciuta". C'è un modo per farlo visualizzare un nome per la posizione? Non vedo alcuna chiave per questo nelle opzioni per il dizionario degli indirizzi ...
Tom Hamming,

5
@ Mr.Jefferson Imposta la proprietà name di MKMapItem
matt

5

Ecco una lezione che utilizza la soluzione di nevan king completata in 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)
}

4

Ho trovato fastidioso che usando http://maps.apple.com?q= ... la configurazione del link apra prima il browser Safari sui dispositivi più vecchi.

Quindi per un dispositivo iOS 5 che apre la tua app con un riferimento a maps.apple.com i passaggi sembrano:

  1. fai clic su qualcosa nell'app e fa riferimento all'URL maps.apple.com
  2. safari apre il link
  3. il server maps.apple.com reindirizza all'URL maps.google.com
  4. l'URL maps.google.com viene interpretato e apre l'app google Maps.

Penso che i passaggi (molto ovvi e confusi) 2 e 3 siano fastidiosi per gli utenti. Pertanto controllo la versione del sistema operativo ed eseguo maps.google.com o maps.apple.com sul dispositivo (per le versioni del sistema operativo iOS 5 o iOS 6).


Questo è quello che sto facendo anch'io. Sembra l'approccio migliore.
Tom Hamming,

3

La mia ricerca su questo tema mi ha portato alle seguenti conclusioni:

  1. Se usi maps.google.com, aprirà la mappa in Safari per ogni iOS.
  2. Se usi maps.apple.com, aprirà la mappa nell'applicazione mappe di iOS 6 e funzionerà anche con iOS 5 e in iOS 5 aprirà la mappa normalmente in Safari.

3

Se invece vuoi aprire Google Maps (o offrire come opzione secondaria), puoi utilizzare gli schemi comgooglemaps://e comgooglemaps-x-callback://URL documentati qui .


3

Prima di lanciare l'URL, rimuovi qualsiasi carattere speciale dall'URL e sostituisci gli spazi con +. Questo ti farà risparmiare alcuni mal di testa:

    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];
        }

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


2

Aggiornato a Swift 4 basato sulla risposta di @ 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)
}

1

Non usando le mappe, semplicemente usando programmaticamente un'azione UiButton, questo ha funzionato benissimo per me.

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

                }

Potresti distribuire un po 'di questo codice un po'. Ad esempio, ho inserito la variabile come variabile a livello di classe, l'ho riempita con un'altra funzione e poi, quando premuto, il pulsante ha semplicemente preso ciò che era nella variabile e lo ha cancellato per usarlo in un URL.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.