Ouvrir l'application Maps par programme dans iOS 6

159

Avant iOS 6, l'ouverture d'une URL comme celle-ci ouvrirait l'application (Google) Maps:

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

Désormais, avec la nouvelle implémentation Apple Maps, cela ouvre simplement Mobile Safari à Google Maps. Comment puis-je accomplir le même comportement avec iOS 6? Comment ouvrir l'application Maps par programme et la faire pointer vers un emplacement / une adresse / une recherche / quoi que ce soit?

Tom Hamming
la source

Réponses:

281

Voici la méthode officielle d'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 vous souhaitez obtenir des instructions de conduite ou de marche vers l'emplacement, vous pouvez inclure un mapItemForCurrentLocationavec le MKMapItemdans le tableau +openMapsWithItems:launchOptions:et définir les options de lancement de manière appropriée.

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

Vous pouvez conserver votre iOS 5 d'origine et le code inférieur dans une elsedéclaration ultérieure if. Notez que si vous inversez l'ordre des éléments dans le openMapsWithItems:tableau, vous obtiendrez des directions entre les coordonnées et votre emplacement actuel. Vous pouvez probablement l'utiliser pour obtenir des directions entre deux emplacements en passant un MKMapItemélément de carte construit au lieu de l'élément de carte de localisation actuel. Je n'ai pas essayé ça.

Enfin, si vous avez une adresse (sous forme de chaîne) à laquelle vous souhaitez accéder, utilisez le géocodeur pour créer un MKPlacemark, via 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];

    }];
}
roi nevan
la source
Le code fonctionne très bien pour iOS 6. Cela vaut la peine d'être mentionné si l'itinéraire que nous voulons est de l'emplacement de l'utilisateur actuel vers une destination, alors pas besoin de passer currentLocationMapItem.
Philip007
1
Le fait que vous ayez utilisé les coordonnées de Tombouctou rend la réponse encore meilleure :)
sachadso
+1 pour avoir mentionné qu'il s'agit d'iOS 6 uniquement et que vous avez besoin d'une solution de secours
Henrik Erlandsson
2
comment puis-je accéder à mon application actuelle à partir des applications cartographiques?
Apple
1
Quel est donc l'emplacement que je sélectionne lorsqu'il ouvre l'application Apple Maps, il affiche une alerte "Les directions n'ont pas pu être trouvées entre ces emplacements ios 6", puis il ne fait rien? Toute aide
NaXir
80

J'ai trouvé la réponse à ma propre question. Apple documente son format d'URL de cartes ici . Il semble que vous puissiez essentiellement remplacer maps.google.compar maps.apple.com.

Mise à jour: Il s'avère que la même chose est vraie dans MobileSafari sur iOS 6; en appuyant sur un lien pour http://maps.apple.com/?q=...ouvrir l'application Maps avec cette recherche, de la même manièrehttp://maps.google.com/?q=... que dans les versions précédentes. Cela fonctionne et est documenté dans la page liée ci-dessus.

MISE À JOUR: Cela répond à ma question relative au format URL. Mais la réponse de nevan king ici (voir ci-dessous) est un excellent résumé de l'API Maps actuelle.

Tom Hamming
la source
1
Intéressant. Si vous ouvrez un navigateur sur maps.apple.com, il redirige vers maps.google.com. Je me demande combien de temps cela va durer?
pir800 du
@ pir800 - Je me demandais en fait ce qui se passerait si vous appuyez sur un lien vers maps.apple.com dans Safari sur iOS 6. Je l'ai essayé, et il va à Maps de la même manière que sur les versions iOS précédentes lorsque vous avez appuyé un lien vers maps.google.com. Je pense que c'est un bon pari qu'ils redirigent vers Google maps afin que les auteurs de sites Web puissent simplement pointer des liens de carte vers maps.apple.com et le faire fonctionner sur iOS dans Maps mais fonctionner normalement sur tous les autres clients. Mais je voudrais vérifier cela avant de changer tous les liens de ma carte pour qu'ils pointent vers maps.apple.com!
Tom Hamming
@ pir800 - pour moi, ouvrir maps.apple.com dans un navigateur m'amène à apple.com/ios/maps . Peut-être que mon commentaire précédent est un vœu pieux.
Tom Hamming
Je voulais dire si vous essayez d'interroger une adresse ou une coordonnée. Essayez maps.apple.com/?q=los angeles, ca. Vous pouvez l'ouvrir sur votre ordinateur de bureau et il sera
redirigé
Existe-t-il un moyen d'ajouter le mode de transit à cette requête? (marcher / conduire). n'a trouvé aucune référence à ce sujet sur le Web.
Lirik
41

La meilleure façon de le faire est d'appeler la nouvelle méthode iOS 6 sur MKMapItem openInMapsWithLaunchOptions:launchOptions

Exemple:

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

Cela lancera la navigation pour conduire à partir de l'emplacement actuel.

zvonicek
la source
1
OK, alors quel est le moyen le plus simple d'obtenir une instance de MKMapItemquand tout ce que j'ai est une adresse? Cette API semble un peu compliquée pour ce cas d'utilisation simple.
Tom Hamming
MKPlacemark * endLocation = [[MKPlacemark alloc] initWithCoordinate: nil addressDictionary: yourAdressDictHere]; vous pouvez remettre une adresse dictonaire
mariusLAN
7

Je vois que vous avez trouvé le "schéma" de l'url maps.apple.com. C'est un bon choix car il redirigera automatiquement les anciens appareils vers maps.google.com. Mais pour iOS 6, il existe une nouvelle classe dont vous voudrez peut-être profiter: MKMapItem .

Deux méthodes qui vous intéressent:

  1. -openInMapsWithLaunchOptions: - appelez-le sur une instance MKMapItem pour l'ouvrir dans Maps.app
  2. + openMapsWithItems: launchOptions: - appelez-le sur la classe MKMapItem pour ouvrir un tableau d'instances MKMapItem.
Filip Radelic
la source
Cela semble utile. Mais cela semble aussi un peu plus compliqué à utiliser; vous devez init MKMapItemavec un MKPlacemark, ce que vous obtenez en fournissant une paire latitude / longitude et un dictionnaire d'adresses. Cela semble plus simple à ouvrir http://maps.apple.com/?q=1+infinite+loop+cupertino+ca. Y a-t-il un avantage à utiliser MKMapItemlorsque tout ce que vous voulez faire est d'afficher une adresse dans Maps?
Tom Hamming
Vous n'avez pas besoin d'initialiser un MKMapItemsi vous n'avez pas déjà une référence à celui que vous souhaitez utiliser. Il suffit d' utiliser la méthode de classe, +openMapsWithItems:launchOptions:sur MKMapItemfaire la même chose.
Mark Adams
@MarkAdams cette méthode de classe prend un tableau d'instances de classe, donc oui, il doit en avoir au moins une initialisée.
Filip Radelic du
Donc, dans une situation où j'ai des coordonnées GPS à ouvrir, mais pas d'adresse, j'utilise l' MKMapItemAPI et elle dépose un point sur la carte intitulé "Emplacement inconnu". Existe-t-il un moyen de lui faire afficher un nom pour l'emplacement? Je ne vois aucune clé pour cela dans les options du dictionnaire d'adresses ...
Tom Hamming
5
@ Mr.Jefferson Définir la propriété name de MKMapItem
mat
5

Voici une classe utilisant la solution de nevan king réalisée dans 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
la source
4

J'ai trouvé ennuyeux d'utiliser le http://maps.apple.com?q= configuration du lien ... ouvre d'abord le navigateur Safari sur les appareils plus anciens.

Ainsi, pour un appareil iOS 5 ouvrant votre application avec une référence à maps.apple.com, les étapes ressemblent à:

  1. vous cliquez sur quelque chose dans l'application et cela fait référence à l'url de maps.apple.com
  2. safari ouvre le lien
  3. le serveur maps.apple.com redirige vers l'url maps.google.com
  4. l'URL de maps.google.com est interprétée et ouvre l'application google Maps.

Je pense que les étapes 2 et 3 (très évidentes et déroutantes) sont ennuyeuses pour les utilisateurs. Par conséquent, je vérifie la version du système d'exploitation et j'exécute maps.google.com ou maps.apple.com sur l'appareil (pour les versions du système d'exploitation respectivement ios 5 ou ios 6).

EeKay
la source
C'est ce que je fais aussi. Cela semble être la meilleure approche.
Tom Hamming
3

Mes recherches sur cette question m'amènent aux conclusions suivantes:

  1. Si vous utilisez maps.google.com, il ouvrira la carte dans safari pour chaque iOS.
  2. Si vous utilisez maps.apple.com, il ouvrira la carte dans l'application cartographique d'ios 6 et fonctionnera également très bien avec ios 5 et dans ios 5, il ouvrira la carte comme d'habitude dans safari.
Honey Jain
la source
3

Si vous souhaitez plutôt ouvrir Google Maps (ou proposer une option secondaire), vous pouvez utiliser les schémas d'URL comgooglemaps://et comgooglemaps-x-callback://documentés ici .

Johan Kool
la source
3

Avant de lancer url, supprimez tout caractère spécial de l'url et remplacez les espaces par +. Cela vous évitera quelques maux de tête:

    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
la source
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
la source
2

Mise à jour vers Swift 4 en fonction de la réponse 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
la source
1

Ne pas utiliser de cartes, mais simplement utiliser une action UiButton par programme, cela a très bien fonctionné pour moi.

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

                }

Vous pouvez diffuser un peu de ce code. Par exemple, j'ai mis la variable en tant que variable de niveau de classe, j'ai fait remplir une autre fonction, puis, lorsque j'ai appuyé sur le bouton, j'ai simplement pris ce qui se trouvait dans la variable et l'ai nettoyé pour être utilisé dans une URL.

Christopher Wade Cantley
la source