【问题标题】:Programmatically open Maps app in iOS 6在 iOS 6 中以编程方式打开地图应用
【发布时间】:2012-09-12 07:51:47
【问题描述】:

在 iOS 6 之前,打开这样的 URL 会打开 (Google) 地图应用:

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

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

【问题讨论】:

    标签: ios objective-c ios6 mapkit


    【解决方案1】:

    这是 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: 的数组中包含mapItemForCurrentLocationMKMapItem,并适当设置启动选项。

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

    您可以在else 语句中保留您原来的iOS 5 及更低版本的代码if。请注意,如果您颠倒 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];
    
        }];
    }
    

    【讨论】:

    • 该代码适用于 iOS 6。值得一提的是,如果我们想要的路线是从当前用户位置到目的地,则无需传入 currentLocationMapItem
    • 您使用 Tombouctou 坐标的事实让答案变得更好:)
    • +1 表示它仅适用于 iOS 6 并且您需要一个备用系统
    • 如何从地图应用导航到我当前的应用?
    • 我在打开苹果地图应用程序时选择了什么位置,它显示警报“在这些位置 ios 6 之间找不到方向”,然后它什么也不做?任何帮助
    【解决方案2】:

    找到了我自己问题的答案。 Apple 记录其地图 URL 格式 here。看起来您基本上可以将maps.google.com 替换为maps.apple.com

    更新:原来在 iOS 6 上的 MobileSafari 中也是如此;点击指向http://maps.apple.com/?q=... 的链接会打开带有该搜索的地图应用程序,就像http://maps.google.com/?q=... 在以前的版本中所做的那样。这有效,并记录在上面链接的页面中。

    更新:这回答了我关于 URL 格式的问题。但是 nevan king 的回答 here(见下文)是对实际 Maps API 的出色总结。

    【讨论】:

    • 有趣。如果您打开浏览器访问 maps.apple.com,它会重定向到 maps.google.com。我想知道这会持续多久?
    • @pir800 - 我实际上只是想知道如果您在 iOS 6 上的 Safari 中点击指向 maps.apple.com 的链接会发生什么。我试过了,它以同样的方式进入地图当您点击指向 maps.google.com 的链接时,在以前的 iOS 版本上执行此操作。我认为他们重定向到谷歌地图是一个不错的选择,这样网站作者就可以将地图链接指向 maps.apple.com 并让它在 iOS 上的 Maps 上运行,但在所有其他客户端上正常运行。但我想在将所有地图链接更改为指向 maps.apple.com 之前以某种方式验证这一点!
    • @pir800 - 对我来说,在浏览器中打开 maps.apple.com 会将我带到 apple.com/ios/maps。也许我之前的评论是一厢情愿。
    • 我的意思是如果您尝试查询地址或坐标。试试 maps.apple.com/?q=los angeles, ca。您可以在台式机上打开它,它会转发到 maps.google.com
    • 有没有办法将公交模式添加到该查询中? (步行/开车)。在网上找不到任何关于它的参考。
    【解决方案3】:

    最好的方法是在MKMapItemopenInMapsWithLaunchOptions:launchOptions上调用新的iOS 6方法

    例子:

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

    这将启动从当前位置驾驶的导航。

    【讨论】:

    • 好的,那么当我只有一个地址时,获取MKMapItem 实例的最简单方法是什么?对于这个简单的用例,这个 API 似乎有点复杂。
    • MKPlacemark *endLocation = [[MKPlacemark alloc] initWithCoordinate:nil addressDictionary:yourAdressDictHere];您可以在中提供地址字典
    【解决方案4】:

    我看到您找到了 maps.apple.com 网址“方案”。这是一个不错的选择,因为它会自动将旧设备重定向到 maps.google.com。但是对于 iOS 6,您可能想利用一个新类:MKMapItem

    你感兴趣的两种方法:

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

    【讨论】:

    • 这看起来很有用。但它的使用似乎也有点复杂;你必须 init MKMapItemMKPlacemark,通过提供纬度/经度对和地址字典来获得。打开http://maps.apple.com/?q=1+infinite+loop+cupertino+ca 似乎更简单。当您只想在地图中显示地址时,使用MKMapItem 是否有优势?
    • 如果您还没有想要使用的引用,则不必初始化MKMapItem。只需使用类方法 +openMapsWithItems:launchOptions: on MKMapItem 来做同样的事情。
    • @MarkAdams 那个类方法需要一组类的实例,所以是的,他至少需要初始化一个。
    • 所以在我有 GPS 坐标要打开但没有地址的情况下,我使用MKMapItem API,它会在地图上放置一个标记为“未知位置”的点。有没有办法让它显示该位置的名称?我在地址字典的选项中没有看到任何键...
    • @Mr.Jefferson 设置MKMapItem的name属性
    【解决方案5】:

    这是一个使用 Swift 完成的 nevan king 解决方案的课程:

    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=... 链接设置会首先在旧设备上打开 safari 浏览器,这很烦人。

      因此,对于使用 maps.apple.com 引用打开您的应用程序的 iOS 5 设备,步骤如下所示:

      1. 您单击应用程序中的某个内容,它引用了 maps.apple.com 网址
      2. Safari 会打开链接
      3. maps.apple.com 服务器重定向到 maps.google.com 网址
      4. maps.google.com 网址被解析并打开谷歌地图应用程序。

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

      【讨论】:

      • 这也是我正在做的。似乎是最好的方法。
      【解决方案7】:

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

      1. 如果您使用 maps.google.com,那么它将在 Safari 中为每个 ios 打开地图。
      2. 如果您使用 maps.apple.com,它将在 ios 6 的地图应用程序中打开地图,并且还可以在 ios 5 中使用,而在 ios 5 中,它会在 safari 中正常打开地图。

      【讨论】:

        【解决方案8】:

        如果您想改为打开 Google 地图(或作为辅助选项提供),您可以使用here 记录的comgooglemaps://comgooglemaps-x-callback:// URL 方案。

        【讨论】:

          【解决方案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】:

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2013-02-19
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-02-20
                  • 2020-10-04
                  • 1970-01-01
                  • 2020-11-29
                  • 1970-01-01
                  相关资源
                  最近更新 更多