Программно открыть приложение "Карты" в iOS 6

До iOS 6, открыв такой URL-адрес, вы откроете приложение Google Maps:

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

Теперь с новой реализацией Apple Maps это просто открывает Mobile Safari для Google Maps. Как я могу выполнить одно и то же поведение с iOS 6? Как программно открыть приложение "Карты" и указать его на конкретное местоположение/адрес/поиск/независимо?

Ответ 1

Нашел ответ на мой собственный вопрос. Apple документирует формат URL-адресов своих карт здесь. Похоже, вы можете заменить maps.google.com на maps.apple.com.

Обновление: Оказывается, то же самое верно и в MobileSafari на iOS 6; нажатие ссылки на http://maps.apple.com/?q=... открывает приложение "Карты" с этим поиском, так же, как и http://maps.google.com/?q=... в предыдущих версиях. Это работает и документируется на странице, указанной выше.

ОБНОВЛЕНИЕ: Это отвечает на мой вопрос, касающийся формата URL. Но nevan king отвечает здесь (см. Ниже) - отличное резюме фактического API Карт.

Ответ 2

Здесь официальный путь 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];
}

Если вы хотите получить инструкции по вождению или ходьбе в этом месте, вы можете включить mapItemForCurrentLocation с MKMapItem в массиве в +openMapsWithItems:launchOptions: и соответствующим образом установить параметры запуска.

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

Вы можете сохранить исходный код iOS 5 и нижний код в инструкции else после этого if. Обратите внимание: если вы измените порядок элементов в массиве openMapsWithItems:, вы получите указания от координаты к текущему местоположению. Вероятно, вы можете использовать его для направления между любыми двумя точками, передав построенный MKMapItem вместо текущего элемента карты местоположения. Я этого не пробовал.

Наконец, если у вас есть адрес (как строка), к которому вы хотите, используйте геокодер для создания MKPlacemark, используя 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 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];

    }];
}

Ответ 3

Лучший способ сделать это - вызывать новый метод iOS 6 на MKMapItem openInMapsWithLaunchOptions:launchOptions

Пример:

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

Это начнет навигацию для вождения из текущего местоположения.

Ответ 4

Я вижу, что вы нашли схему maps.apple.com url. Это хороший выбор, потому что он автоматически перенаправляет старые устройства на maps.google.com. Но для iOS 6 есть новый класс, который вы, возможно, захотите использовать: MKMapItem.

Два метода, которые вас интересуют:

Ответ 5

Вот класс с использованием решения nevan king, завершенного в 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)
}

Ответ 6

Мне было досадно, что с помощью http://maps.apple.com?q=... настройка ссылок открывает браузер сафари сначала на старых устройствах.

Итак, для устройства iOS 5, открывающего ваше приложение со ссылкой на maps.apple.com, шаги выглядят так:

  • вы нажимаете что-то в приложении и ссылаетесь на адрес maps.apple.com
  • сафари открывает ссылку
  • сервер maps.apple.com перенаправляет URL-адрес maps.google.com
  • URL-адрес maps.google.com интерпретируется и открывает приложение Google Maps.

Я думаю, что (очень очевидные и запутывающие) шаги 2 и 3 раздражают пользователей. Поэтому я проверяю версию os и запускаю maps.google.com или maps.apple.com на устройстве (для версий ОС iOS 5 или iOS 6).

Ответ 7

Мои исследования по этому вопросу привели меня к следующим выводам:

  • Если вы используете maps.google.com, тогда он откроет карту в сафари для каждого ios.
  • Если вы используете maps.apple.com, тогда он откроет карту в приложении карты ios 6, а также будет работать с ios 5, а в ios 5 он откроет карту как обычно в сафари.

Ответ 8

Если вы хотите открыть Google Карты вместо этого (или предлагать в качестве вторичного варианта), вы можете использовать схемы URL comgooglemaps:// и comgooglemaps-x-callback://, зарегистрированные здесь.

Ответ 9

Перед запуском url удалите любой специальный символ из url и замените пробелы на+. Это сэкономит вам несколько головных болей:

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

Ответ 10

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

Ответ 11

Не используя карты, просто программно используя действие UiButton, это отлично поработало для меня.

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

                }

Вы можете немного расширить часть этого кода. Например, я поместил переменную как переменную уровня класса, добавила другую функцию, а затем нажала кнопку, просто взяла то, что было в переменной, и вычистила ее для использования в URL-адресе.

Ответ 12

Обновлен до Swift 4 на основе ответа @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)
}