在 iOS6中以编程方式打开地图应用程序

在 iOS6之前,打开这样的 URL 会打开(谷歌)地图应用程序:

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

现在,随着新的苹果地图的实现,这只是打开移动 Safari 到谷歌地图。我如何在 iOS6中实现同样的行为呢?我如何程序化地打开地图应用程序,并让它指向一个特定的位置/地址/搜索/无论什么?

100038 次浏览

找到了我自己问题的答案。苹果公司记录其地图 URL 格式 给你。看起来你基本上可以用 maps.apple.com代替 maps.google.com

更新: 在 MobileSafari iOS 6上也是如此,点击一个到 http://maps.apple.com/?q=...的链接就可以打开地图应用的搜索,就像 http://maps.google.com/?q=...在以前的版本中做的一样。这是可行的,并在上面链接的页面中进行了记录。

更新: 这回答了我关于 URL 格式的问题。但是 Nevan King 的答案 给你(见下文)是对实际的 Maps API 的极好总结。

看来你找到 maps.apple.com 的网址“ scheme”了。这是一个很好的选择,因为它会自动将旧设备重定向到 maps.google.com。但是对于 iOS6,有一个新的类你可能想要利用: MKMapItem

你感兴趣的两种方法:

  1. - openInMapsWithLaunchOptions: -在 MKMapItem 实例上调用它,在 Maps.app 中打开它
  2. + openMapsWithItems: launchOptions: -在 MKMapItem 类上调用它以打开 MKMapItem 实例的数组。

最好的方法是在 MKMapItem openInMapsWithLaunchOptions:launchOptions上调用新的 iOS6方法

例如:

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

这将启动从当前位置开车的导航。

我发现它恼人的使用 http://maps.apple.com?q=... 链接设置打开 Safari 浏览器首先在旧设备。

因此,对于一个 iOS5设备打开你的应用程序并引用 maps.apple.com 的步骤如下:

  1. 你点击应用程序中的某个地方,它就会指向 maps.apple.com 的网址
  2. Safari 打开链接
  3. Apple.com 服务器重定向到 maps.google.com URL
  4. 这个 Maps.google.com 地址会被解释并打开 google 地图应用程序。

我认为(非常明显和令人困惑的)步骤2和3对用户来说很烦人。 因此,我检查操作系统版本,并在设备上运行 maps.google.com 或 maps.apple.com。Ios 5或 ios 6操作系统版本)。

我对这个问题的研究使我得出以下结论:

  1. 如果你使用 maps.google.com,那么它会在 safari 中为每个 ios 打开地图。
  2. 如果您使用 maps.apple.com,那么它将在 ios 6的地图应用程序中打开地图,并且在 ios 5中也可以很好地工作,在 ios 5中,它将在 safari 中像平常一样打开地图。

以下是苹果的官方方式:

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

如果你想得到驾驶或步行指令的位置,你可以包括一个 mapItemForCurrentLocationMKMapItem在数组中的 +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];
}

if之后,你可以在 else语句中保留原来的 iOS5和更低的代码。请注意,如果您反转 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'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];


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

下面是一个使用 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)
}

如果你想打开谷歌地图(或作为次要选项提供) ,你可以使用 comgooglemaps://comgooglemaps-x-callback:// URL 方案文档 给你

不使用地图,只是通过编程使用 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 中使用。

在启动 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];
}

根据@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)
}