Программно открыть приложение "Карты" в 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)
}