以编程方式在iOS 6中打开地图应用程序
在iOS 6之前,像这样打开一个URL会打开(Google)地图应用程序:
NSURL *url = [NSURL URLWithString:@"http://maps.google.com/?q=New+York"]; [[UIApplication sharedApplication] openURL:url];
现在,随着新的苹果地图的实施,这只是打开移动Safari到谷歌地图。 我怎样才能完成与iOS 6相同的行为? 我如何以编程方式打开地图应用程序,并指向特定的位置/地址/search/什么?
这是苹果的官方方式:
// 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]; }
如果您想获取驾驶或步行指令到该位置,可以在+openMapsWithItems:launchOptions:
中的数组中包含一个mapItemForCurrentLocation
和+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和更低版本的代码。 请注意,如果您颠倒openMapsWithItems:
数组中项目的顺序,您将获得从坐标到当前位置的方向。 你可以通过传递一个构造的MKMapItem
而不是当前的位置图项来使用它来获取任意两个位置之间的方向。 我没有尝试过。
最后,如果你有一个你想要的地址(作为一个string),使用地理编码器通过CLPlacemark
创build一个MKPlacemark
。
// 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]; }]; }
find了我自己的问题的答案。 苹果在这里logging它的地图URL格式。 它看起来像你可以基本上用maps.apple.com
取代maps.google.com
。
更新:事实certificate,iOS 6上的MobileSafari也是如此; 点击一个链接http://maps.apple.com/?q=...
打开地图应用程序的search,同样的方式http://maps.google.com/?q=...
以前做过版本。 这工作,并logging在上面链接的页面。
更新:这回答了我有关URL格式的问题。 但是,内文国王的答案在这里 (见下文)是实际的地图API的一个很好的总结。
最好的方法是在MKMapItem
上调用新的iOS 6方法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];
这将开始从当前位置驾驶的导航。
我看到你发现了maps.apple.com url“scheme”。 这是一个不错的select,因为它会自动将旧设备redirect到maps.google.com。 但是对于iOS 6,您可能想要利用以下新类: MKMapItem 。
你感兴趣的两种方法:
- -openInMapsWithLaunchOptions: – 在一个MKMapItem实例上调用它来在Maps.app中打开它
- + openMapsWithItems:launchOptions: – 在MKMapItem类上调用它打开一个MKMapItem实例数组。
这是一个使用nevan king在Swift中完成的解决scheme:
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) }
我发现使用http://maps.apple.com?q= …链接设置首先在较旧的设备上打开Safari浏览器令人讨厌。
因此,对于iOS 5设备,通过引用maps.apple.com打开您的应用程序,步骤如下所示:
- 你点击应用程序中的东西,它指的是maps.apple.comurl
- safari打开链接
- maps.apple.com服务器redirect到maps.google.comurl
- maps.google.comurl被解释并打开谷歌地图应用程序。
我认为(非常明显的和令人困惑的)步骤2和3对于用户来说是烦人的。 因此,我检查了操作系统版本,并在设备上运行maps.google.com或maps.apple.com(用于响应ios 5或ios 6操作系统版本)。
我对这个问题的研究使我得出以下结论:
- 如果您使用maps.google.com,那么它将在Safari中为每个ios打开地图。
- 如果您使用maps.apple.com,那么它将打开地图应用程序的iOS 6中的地图,也与ios 5和ios 5一起工作,它在Safari浏览器中正常打开地图。
如果您想打开Google地图(或作为辅助选项提供),则可以使用comgooglemaps://
和comgooglemaps-x-callback://
URLscheme。
在启动url之前,从url中删除任何特殊字符,并用+replace空格。 这会为您节省一些头痛的问题:
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]; }
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
不使用地图,只是以编程方式使用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!) }
你可以把这些代码分散一点。 例如,我把variables作为一个类的variables,有另一个函数来填充它,然后当按下button时,只需要把variables中的内容清理出来,并将其用在URL中。
根据@PJeremyMalouf的回答,更新为Swift 4:
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) }