Öffnen Sie programmgesteuert die Karten-App in iOS 6

159

Vor iOS 6 öffnete das Öffnen einer solchen URL die (Google) Maps-App:

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

Mit der neuen Apple Maps-Implementierung wird Mobile Safari nur für Google Maps geöffnet. Wie kann ich mit iOS 6 dasselbe Verhalten erreichen? Wie öffne ich programmgesteuert die Karten-App und lasse sie auf einen bestimmten Ort / eine bestimmte Adresse / Suche / was auch immer verweisen?

Tom Hamming
quelle

Antworten:

281

Hier ist der offizielle Apple-Weg:

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

Wenn Sie erhalten mögen Auto fahren oder Anweisungen an den Ort zu Fuß, können Sie eine sind mapItemForCurrentLocationmit dem MKMapItemin der Anordnung in +openMapsWithItems:launchOptions:und um die Startoptionen entsprechend gesetzt.

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

Danach können Sie Ihren ursprünglichen iOS 5 und niedrigeren Code in einer elseAnweisung beibehalten if. Beachten Sie, dass Sie beim Umkehren der Reihenfolge der Elemente im openMapsWithItems:Array Anweisungen von der Koordinate zu Ihrem aktuellen Standort erhalten. Sie könnten es wahrscheinlich verwenden, um Wegbeschreibungen zwischen zwei beliebigen Standorten zu erhalten, indem Sie ein konstruiertes MKMapItemanstelle des aktuellen Standortkartenelements übergeben. Das habe ich nicht versucht.

Schließlich, wenn Sie eine Adresse (als String) , dass Sie Richtungen wollen, verwenden Sie den Geocoder eine erstellen MKPlacemark, haft 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 König
quelle
Der Code funktioniert hervorragend für iOS 6. Erwähnenswert ist jedoch, dass keine Übergabe erforderlich ist, wenn die gewünschte Route vom aktuellen Benutzerstandort zu einem Ziel führt currentLocationMapItem.
Philip007
1
Die Tatsache, dass Sie Tombouctou-Koordinaten verwendet haben, macht die Antwort noch besser :)
Sachadso
+1 für die Erwähnung, dass es nur iOS 6 ist und dass Sie einen Fallback benötigen
Henrik Erlandsson
2
Wie kann ich von Karten-Apps zu meiner aktuellen Anwendung navigieren?
Apple
1
Welchen Ort wähle ich aus, wenn ich die Apple Maps App öffne? Es wird die Warnung angezeigt, dass zwischen diesen Orten ios 6 keine Wegbeschreibung gefunden werden konnte. Dann wird nichts unternommen. Jede Hilfe
NaXir
80

Ich habe die Antwort auf meine eigene Frage gefunden. Apple - Dokumente seine Karten URL - Format hier . Es sieht aus wie Sie im Wesentlichen ersetzen maps.google.commit maps.apple.com.

Update: Es stellt sich heraus, dass dies auch in MobileSafari unter iOS 6 der Fall ist. Durch Tippen auf einen Link http://maps.apple.com/?q=...wird die Karten-App mit dieser Suche geöffnet, http://maps.google.com/?q=...wie in früheren Versionen. Dies funktioniert und ist auf der oben verlinkten Seite dokumentiert.

UPDATE: Dies beantwortet meine Frage zum URL-Format. Die Antwort von nevan king hier (siehe unten) ist jedoch eine hervorragende Zusammenfassung der tatsächlichen Maps-API.

Tom Hamming
quelle
1
Interessant. Wenn Sie einen Browser zu maps.apple.com öffnen, wird er zu maps.google.com weitergeleitet. Ich frage mich, wie lange das dauern wird.
Pir800
@ pir800 - Ich habe mich eigentlich nur gefragt, was passieren würde, wenn Sie in Safari unter iOS 6 auf einen Link zu maps.apple.com tippen. Ich habe es versucht und es geht zu Maps genauso wie in früheren iOS-Versionen, als Sie darauf tippten ein Link zu maps.google.com. Ich denke, es ist eine gute Wette, dass sie zu Google Maps umleiten, damit Website-Autoren nur auf Kartenlinks auf maps.apple.com verweisen und es unter iOS in Maps funktionieren lassen können, aber normal auf allen anderen Clients. Aber ich möchte das irgendwie überprüfen, bevor ich alle meine Kartenlinks so ändere, dass sie auf maps.apple.com verweisen!
Tom Hamming
@ pir800 - Für mich führt das Öffnen von maps.apple.com in einem Browser zu apple.com/ios/maps . Vielleicht ist mein vorheriger Kommentar Wunschdenken.
Tom Hamming
Ich meinte, wenn Sie versuchen, eine Adresse oder Koordinate abzufragen. Versuchen Sie maps.apple.com/?q=los angeles, ca. Sie können es auf Ihrem Desktop-Computer öffnen und es wird an maps.google.com
pir800
Gibt es eine Möglichkeit, den Transitmodus zu dieser Abfrage hinzuzufügen? (Gehen / Fahren). konnte im Web keinen Hinweis darauf finden.
Lirik
41

Der beste Weg, dies zu tun, besteht darin, die neue iOS 6-Methode aufzurufen MKMapItem openInMapsWithLaunchOptions:launchOptions

Beispiel:

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

Dadurch wird die Navigation zum Fahren vom aktuellen Standort aus gestartet.

Zvonicek
quelle
1
OK, was ist der einfachste Weg, um eine Instanz zu erhalten, MKMapItemwenn ich nur eine Adresse habe? Diese API scheint für diesen einfachen Anwendungsfall etwas kompliziert zu sein.
Tom Hamming
MKPlacemark * endLocation = [[MKPlacemark-Zuweisung] initWithCoordinate: nil addressDictionary: yourAdressDictHere]; Sie können eine Adresse Dictonary in
mariusLAN
7

Ich sehe, Sie haben das URL-Schema "maps.apple.com" gefunden. Dies ist eine gute Wahl, da ältere Geräte automatisch zu maps.google.com umgeleitet werden. Für iOS 6 gibt es jedoch eine neue Klasse, die Sie möglicherweise nutzen möchten: MKMapItem .

Zwei Methoden, die Sie interessieren:

  1. -openInMapsWithLaunchOptions: - Rufen Sie es auf einer MKMapItem-Instanz auf, um es in Maps.app zu öffnen
  2. + openMapsWithItems: launchOptions: - Rufen Sie es in der MKMapItem-Klasse auf, um ein Array von MKMapItem-Instanzen zu öffnen.
Filip Radelic
quelle
Das sieht nützlich aus. Es scheint aber auch etwas komplizierter zu sein; Sie müssen init MKMapItemmit einem MKPlacemark, das Sie erhalten, indem Sie ein Längen- / Breitengradpaar und ein Adresswörterbuch bereitstellen. Scheint einfacher zu öffnen http://maps.apple.com/?q=1+infinite+loop+cupertino+ca. Gibt es einen Vorteil bei der Verwendung, MKMapItemwenn Sie lediglich eine Adresse in Maps anzeigen möchten?
Tom Hamming
Sie müssen eine nicht initialisieren, MKMapItemwenn Sie noch keinen Verweis auf eine haben, die Sie verwenden möchten. Verwenden Sie einfach die Klassenmethode, +openMapsWithItems:launchOptions:auf MKMapItemdie gleiche Sache zu tun.
Mark Adams
@MarkAdams, dass die Klassenmethode ein Array von Klasseninstanzen akzeptiert, also muss er mindestens eine initialisiert haben.
Filip Radelic
In einer Situation, in der ich GPS-Koordinaten öffnen muss, aber keine Adresse, verwende ich die MKMapItemAPI und es wird ein Punkt auf der Karte mit der Bezeichnung "Unbekannter Ort" abgelegt. Gibt es eine Möglichkeit, einen Namen für den Standort anzuzeigen? Ich sehe keine Schlüssel dafür in den Optionen für das Adresswörterbuch ...
Tom Hamming
5
@ Mr.Jefferson Setzen Sie die Namenseigenschaft von MKMapItem
matt
5

Hier ist eine Klasse mit der in Swift abgeschlossenen Lösung von nevan king:

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
quelle
4

Ich fand es ärgerlich, dass die Verwendung des Link-Setups http://maps.apple.com?q= ... den Safari-Browser zuerst auf älteren Geräten öffnet.

Für ein iOS 5-Gerät, das Ihre App mit einem Verweis auf maps.apple.com öffnet, sehen die Schritte folgendermaßen aus:

  1. Wenn Sie in der App auf etwas klicken, verweist es auf die URL maps.apple.com
  2. Safari öffnet den Link
  3. Der Server "maps.apple.com" leitet zur URL "maps.google.com" weiter
  4. Die URL von maps.google.com wird interpretiert und öffnet die Google Maps-App.

Ich denke, dass die (sehr offensichtlichen und verwirrenden) Schritte 2 und 3 die Benutzer nerven. Daher überprüfe ich die Betriebssystemversion und führe entweder maps.google.com oder maps.apple.com auf dem Gerät aus (für die Betriebssystemversionen ios 5 bzw. ios 6).

EeKay
quelle
Das mache ich auch. Scheint der beste Ansatz zu sein.
Tom Hamming
3

Meine Forschung zu diesem Thema führte mich zu folgenden Schlussfolgerungen:

  1. Wenn Sie maps.google.com verwenden, wird die Karte in Safari für jedes iOS geöffnet.
  2. Wenn Sie maps.apple.com verwenden, wird die Karte in der Kartenanwendung von ios 6 geöffnet und funktioniert auch mit ios 5 und in ios 5 wird die Karte wie gewohnt in Safari geöffnet.
Honig Jain
quelle
3

Wenn Sie stattdessen Google Maps öffnen möchten (oder als sekundäre Option anbieten möchten), können Sie die hier dokumentierten comgooglemaps://und comgooglemaps-x-callback://URL-Schemata verwenden .

Johan Kool
quelle
3

Entfernen Sie vor dem Starten der URL alle Sonderzeichen aus der URL und ersetzen Sie die Leerzeichen durch +. Dies erspart Ihnen einige Kopfschmerzen:

    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
quelle
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
quelle
2

Aktualisiert auf Swift 4 basierend auf der Antwort von @ 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
quelle
1

Ohne Karten, nur programmgesteuert mit einer UiButton-Aktion, hat dies für mich hervorragend funktioniert.

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

                }

Sie könnten einen Teil dieses Codes ein wenig verbreiten. Zum Beispiel habe ich die Variable als Variable auf Klassenebene eingefügt, sie von einer anderen Funktion ausfüllen lassen. Wenn ich dann auf die Schaltfläche drückte, nahm ich einfach das, was in der Variablen enthalten war, und bereinigte es, um es in einer URL zu verwenden.

Christopher Wade Cantley
quelle