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

159

iOS 6之前,打开如下URL会打开(谷歌)地图应用程序:

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

现在有了新的Apple Maps实现,这只是打开Mobile Safari到Google Maps。我该如何在iOS 6中实现相同的行为?我如何以编程方式打开地图应用并将其指向特定位置/地址/搜索/其他什么?

12个回答

281

这是官方的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];
}
如果您想获取到该位置的驾车或步行路线指示,您可以在 +openMapsWithItems:launchOptions: 中的数组中包含一个带有 MKMapItemmapItemForCurrentLocation,并适当设置启动选项。
// 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语句中,可以保留原始iOS 5及以下版本的代码。请注意,如果您颠倒openMapsWithItems:数组中项目的顺序,则会获得从坐标点当前位置的方向。您可以通过传递一个构建的MKMapItem而不是当前位置地图项来使用它来获取任意两个位置之间的方向。我没有尝试过。

最后,如果您有一个地址(作为字符串)想要获取方向,请使用地理编码器通过CLPlacemark创建一个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];

    }];
}

1
你使用的是通布图坐标系,这使得答案变得更好了 :) - sachadso
2
我该如何从地图应用程序导航到我的当前应用程序? - Apple
1
无论我在哪个位置打开苹果地图应用程序,它都会显示警告“这些位置之间找不到方向 iOS 6”,然后什么也不做?有什么帮助吗? - NaXir
@MarkAmery,我觉得我想说的是相对于被接受的回答采用URL方案,这个是“官方”的。虽然iOS 6检查是官方的,但是这个来自苹果文档。 - nevan king
@nevanking 实际上错误出现在代码的其他地方。感谢您澄清这也适用于iOS 7。 - ErikAndren
显示剩余10条评论

80

我找到了自己问题的答案。苹果记录了其地图URL格式在此处。看起来,你可以用maps.apple.com来替换maps.google.com

更新:实际上,在iOS 6上的MobileSafari中也是如此;点击链接http://maps.apple.com/?q=...会打开带有该搜索的地图应用程序,就像之前版本的http://maps.google.com/?q=...一样。 这个方法可以使用,并且已经记录在上面链接的页面中。

更新:这回答了我关于URL格式的问题。但 nevan king的答案(请参见下文)是关于实际地图API的优秀总结。


1
有趣。如果你打开浏览器到maps.apple.com,它会重定向到maps.google.com。我想知道这会持续多久? - pir800
@pir800 - 我其实只是想知道在iOS 6的Safari中点击maps.apple.com链接会发生什么。我试了一下,它会像以前的iOS版本一样跳转到Maps,就像你点击maps.google.com链接时一样。我认为他们正在重定向到Google地图,这样网站作者就可以将地图链接指向maps.apple.com,在iOS上使用Maps,但在所有其他客户端上正常工作。但在更改所有地图链接指向maps.apple.com之前,我想要进行某种验证! - Tom Hamming
@pir800 - 对我来说,在浏览器中打开http://maps.apple.com会将我带到http://www.apple.com/ios/maps/。也许我的先前评论只是一厢情愿的想法。 - Tom Hamming
我是说如果你尝试查询地址或坐标。请尝试在桌面计算机上打开maps.apple.com/?q=los angeles, ca,它会转发到maps.google.com。 - pir800
有没有办法在查询中添加交通方式(步行/驾车)?在网上找不到任何相关的参考资料。 - Lirik

41

最好的方法是在 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];

这将从当前位置开始导航驾驶。


1
好的,那么当我只有一个地址时,获取MKMapItem实例的最简单方法是什么?这个API似乎对于这种简单的用例有点复杂。 - Tom Hamming
MKPlacemark *endLocation = [[MKPlacemark alloc] initWithCoordinate:nil addressDictionary:yourAdressDictHere];你可以将地址字典传递进去。 - mariusLAN

7
我看到您找到了maps.apple.com的URL“scheme”。这是一个不错的选择,因为它会自动将旧设备重定向到maps.google.com。但是对于iOS 6,有一个新的类可以让您充分利用:MKMapItem
您可能感兴趣的两种方法:
1. -openInMapsWithLaunchOptions: - 在MKMapItem实例上调用它以在Maps.app中打开它。 2. +openMapsWithItems:launchOptions: - 在MKMapItem类上调用它以打开一组MKMapItem实例。

看起来很有用。但是使用起来似乎有点复杂;您必须使用MKPlacemark初始化MKMapItem,而MKPlacemark是通过提供纬度/经度对和地址字典来获取的。直接打开http://maps.apple.com/?q=1+infinite+loop+cupertino+ca似乎更简单。当您只想在地图中显示地址时,使用MKMapItem是否有优势? - Tom Hamming
如果您没有对想要使用的 MKMapItem 对象的引用,则无需初始化它。只需在 MKMapItem 上使用类方法 +openMapsWithItems:launchOptions: 即可完成相同的操作。 - Mark Adams
@MarkAdams 那个类方法接受一个类实例的数组作为参数,所以是的,他需要至少初始化一个。 - Filip Radelic
所以在我只有GPS坐标而没有地址的情况下,我使用MKMapItem API,在地图上放置一个标记为“未知位置”的点。有没有办法让它显示该位置的名称?我在地址字典选项中没有看到任何键可以实现这一点... - Tom Hamming
5
请为MKMapItem设置name属性。 - matt

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)
}

4
我发现使用http://maps.apple.com?q=...链接设置在老设备上会先打开safari浏览器,这很烦人。
因此,对于iOS 5设备,在引用maps.apple.com的情况下,步骤如下:
1. 在应用程序中点击某个东西,它将引用maps.apple.com URL 2. Safari打开链接 3. maps.apple.com服务器重定向到maps.google.com URL 4. 解释maps.google.com URL并打开Google Maps应用程序。
我认为(非常明显和令人困惑的)步骤2和3对用户来说很烦人。 因此,我检查操作系统版本,并在设备上运行maps.google.com或maps.apple.com(分别适用于iOS 5或iOS 6操作系统版本)。

这也是我正在做的。看起来是最好的方法。 - Tom Hamming

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

3

如果您想打开谷歌地图(或作为第二个选项提供),您可以使用在此处记录的comgooglemaps://comgooglemaps-x-callback:// URL方案。


3

我的研究得出以下结论:

  1. 如果您使用maps.google.com,则会在每个iOS设备上在Safari中打开地图。
  2. 如果您使用maps.apple.com,则会在iOS 6的地图应用程序中打开地图,并且在iOS 5中也能很好地工作,在iOS 5中它将像通常一样在Safari中打开地图。

2

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接