web-dev-qa-db-fra.com

Ouvrez l'application Maps par programme dans iOS 6

Avant iOS 6, ouvrir une URL de ce type ouvrirait l'application Google (Google):

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 ne fait qu'ouvrir Safari mobile à Google Maps. Comment puis-je accomplir le même comportement avec iOS 6? Comment puis-je ouvrir l'application Maps par programme et la faire pointer vers un emplacement/une adresse/une recherche/quoi que ce soit?

158
Tom Hamming

Trouvé la réponse à ma propre question. Apple documente le format de son URL pour les cartes ici . Il semble que vous puissiez essentiellement remplacer maps.google.com par maps.Apple.com.

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

UPDATE: Ceci répond à ma question concernant le format de l'URL. Mais la réponse de nevan king ici (voir ci-dessous) est un excellent résumé de l’API de Google Maps.

80
Tom Hamming

Voici la manière officielle 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 jusqu'à l'emplacement, vous pouvez inclure un mapItemForCurrentLocation avec le MKMapItem dans le tableau de +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 code iOS 5 d'origine et inférieur dans une instruction else après celle-ci if. Notez que si vous inversez l'ordre des éléments dans le tableau openMapsWithItems:, vous obtiendrez les indications à partir de la coordonnée à votre emplacement actuel. Vous pourriez probablement l’utiliser pour obtenir un itinéraire entre deux emplacements quelconques en passant un MKMapItem construit au lieu de l’élément de carte d’emplacement actuel. Je n'ai pas essayé ça.

Enfin, si vous souhaitez indiquer une adresse (sous forme de chaîne), utilisez le géocodeur pour créer une variable MKPlacemark, au moyen 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];

    }];
}
281
nevan king

La meilleure façon de le faire est d'appeler la nouvelle méthode iOS 6 sur MKMapItemopenInMapsWithLaunchOptions: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 démarrera la navigation pour conduire à partir de la position actuelle.

41
zvonicek

Je vois que vous avez trouvé l'URL "schéma" de 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 pourriez vouloir tirer parti: MKMapItem .

Deux méthodes qui vous intéressent:

  1. - openInMapsWithLaunchOptions: - appelez-le sur une instance de MKMapItem pour l'ouvrir dans Maps.app
  2. + openMapsWithItems: launchOptions: - appelez-le sur la classe MKMapItem pour ouvrir un tableau d'instances MKMapItem.
7
Filip Radelic

Voici une classe utilisant la solution de nevan king complétée à 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)
}
5
PJeremyMalouf

Je trouvais ennuyeux que l’utilisation de la configuration du lien http://maps.Apple.com?q= ... ouvre le navigateur Safari d’abord sur les appareils plus anciens.

Donc, pour un appareil iOS 5 ouvrant votre application avec une référence à maps.Apple.com, les étapes sont les suivantes:

  1. vous cliquez sur quelque chose dans l'application et il fait référence à l'URL maps.Apple.com
  2. safari ouvre le lien
  3. le serveur maps.Apple.com redirige vers l'URL maps.google.com
  4. l'URL 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 gênantes pour les utilisateurs. Par conséquent, je vérifie la version de l'OS et exécute maps.google.com ou maps.Apple.com sur l'appareil (pour les versions respectives d'ios 5 ou ios 6).

4
EeKay

Avant de lancer url, supprimez tout caractère spécial de l’url et remplacez les espaces par +. Cela vous évitera des 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];
        }

Si vous souhaitez ouvrir Google Maps à la place (ou proposer une option secondaire), vous pouvez utiliser les modèles d'URL comgooglemaps:// et comgooglemaps-x-callback:// documentés ici .

3
Johan Kool

Mes recherches sur cette question m'ont amené aux conclusions suivantes:

  1. Si vous utilisez maps.google.com, il ouvrira la carte en 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 parfaitement avec ios 5 et, dans ios 5, l'ouvrira comme d'habitude dans un safari.
3
Honey Jain

Mis à jour en Swift 4 sur la base 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)
}
2
Chris Prince
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
Vinod Joshi

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 pourriez diffuser un peu de ce code un peu. Par exemple, j'ai placé la variable en tant que variable de niveau de classe, une autre fonction l'a remplie, puis, une fois enfoncé, le bouton a simplement pris ce qui était dans la variable et l'a nettoyé pour l'utiliser dans une URL.