如何调用以当前位置为起始地址的路线的iPhone地图


72

我知道可以通过调用openURL带有参数saddrdaddr位置字符串或纬度/经度的google maps URL来启动iPhone maps应用程序(请参见下面的示例)。

但是我想知道是否可以将起始地址设为“当前位置”地图书签,以便可以使用“地图”应用的位置处理代码。我的Google搜索工作毫无成果。

例如:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat: @"http://maps.google.com/maps?saddr=%@&daddr=%@", myLatLong, latlong]]];

除非可以代替调用当前位置书签myLatLong


我正在尝试执行相同的确切功能,并且我已将地图加载到目标位置,但是当我加载google地图时,即使它已经过了几小时或几天,它也会为我提供最新的GPS读数。有时它给我的位置读数有1英里或更多的距离。如何获得准确的当前位置读数?我是否缺少CoreLocation的准确性?thx

Answers:


133

iOS 6之前的版本

您需要使用“核心位置”来获取当前位置,但是使用该经纬度对,您可以获取“地图”以将您从那里路由到街道地址或位置。像这样:

CLLocationCoordinate2D currentLocation = [self getCurrentLocation];
// this uses an address for the destination.  can use lat/long, too with %f,%f format
NSString* address = @"123 Main St., New York, NY, 10001";
NSString* url = [NSString stringWithFormat: @"http://maps.google.com/maps?saddr=%f,%f&daddr=%@",
                    currentLocation.latitude, currentLocation.longitude,
                    [address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[[UIApplication sharedApplication] openURL: [NSURL URLWithString: url]];

最后,如果确实要避免使用CoreLocation显式查找当前位置,而要使用@"http://maps.google.com/maps?saddr=Current+Location&daddr=%@"url,则请参阅我在下面注释中提供的此链接,以了解如何本地化Current + Location字符串。但是,您正在利用另一个未记录的功能,并且正如Jason McCreary在下面指出的那样,它在将来的发行版中可能无法可靠地工作。


iOS 6更新

最初,Google Maps使用Google Maps,但是现在,Apple和Google拥有单独的Maps应用程序。

1)如果您希望使用Google Maps应用进行路由,请使用comgooglemaps URL方案

NSString* url = [NSString stringWithFormat: @"comgooglemaps://?daddr=%@&directionsmode=driving",
                    [address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
BOOL opened = [[UIApplication sharedApplication] openURL: [NSURL URLWithString: url]];

2)要使用Apple Maps,您可以使用MKMapItemiOS 6的新类。 在此处查看Apple API文档

基本上,如果路由到目标坐标latlong),则将使用类似的方法:

    MKPlacemark* place = [[MKPlacemark alloc] initWithCoordinate: latlong addressDictionary: nil];
    MKMapItem* destination = [[MKMapItem alloc] initWithPlacemark: place];
    destination.name = @"Name Here!";
    NSArray* items = [[NSArray alloc] initWithObjects: destination, nil];
    NSDictionary* options = [[NSDictionary alloc] initWithObjectsAndKeys:
                                 MKLaunchOptionsDirectionsModeDriving, 
                                 MKLaunchOptionsDirectionsModeKey, nil];
    [MKMapItem openMapsWithItems: items launchOptions: options];

为了在同一代码中同时支持iOS 6+和iOS 6之前的版本,我建议使用Apple在MKMapItemAPI文档页面上具有的以下代码:

Class itemClass = [MKMapItem class];
if (itemClass && [itemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)]) {
   // iOS 6 MKMapItem available
} else {
   // use pre iOS 6 technique
}

这将假设您的Xcode Base SDK是iOS 6(或最新的iOS)。


2
这比必要的更为复杂。见下面@bob这里传递“当前+位置”作为参数的答案
Willster

1
@Willster:如果有人能弄清楚如何将“当前位置”用作iPad上的参数,我就卖了!
Joe D'Andrea

2
实际上,Willster ..并没有没有必要的复杂。查看该线程的日期。没有OS 4.0。在3.x上,您需要传递坐标。正如乔提到的,您仍然有大量的iPad仍在3.2上,更不用说iPod Touch或用户无法升级的iPhone。另外,还有本地化的问题。如果用户不使用英语,则“当前+位置”不起作用。因此,如果您想使解决方案更可靠,则需要传递坐标。
Nate

1
“知道,我想我今天学到了一些东西。” 拥抱坐标。:)
Joe D'Andrea

4
尽管Current+Location以前可以使用,但在iOS 5.1.1上似乎不再可用。
杰森·麦克雷里

21
NSString* addr = [NSString stringWithFormat:@"http://maps.google.com/maps?daddr=Current Location&saddr=%@",startAddr];
NSURL* url = [[NSURL alloc] initWithString:[addr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[[UIApplication sharedApplication] openURL:url];
[url release];

这仅适用于iPhone / iPod语言设置为英语的情况。如果要支持其他语言,则必须使用本地化的字符串来匹配“地图”书签名称。


2
适用于iPhone,但不适用于iPad。在后一种情况下,我最终从密苏里州的Current开始。:(
乔·安德里亚

我没有iPad可以测试,但是iPad Map应用程序中当前位置的书签的名称是什么?
Tchettane 2011年

至少以美式英语显示为“当前位置” ...除非已将其设置为起点/终点...否则书签列表中将不存在该位置。
Joe D'Andrea

我们需要翻译它,真是太可惜了……我确定有一个特殊的代码,但是……
Thomas Decaux

尽管以前可以使用,但在iOS 5.1.1上似乎不再可用。
杰森·麦克雷里

11

您必须对空格进行编码,但是,可以。在这里看到:stackoverflow.com/questions/4590972/...
Jerph

1
在iPhone上效果很好!在iPad上,我设法降落-我不骗你-当前,密苏里州。:-o
Joe D'Andrea

这行不通。我刚刚尝试在我的iPhone(4.2.6)上使用。文件说它应该,但它不会
JohnO

1
请改用“当前位置”。为我工作。

1
仅当用户将电话语言设置为英语时,此解决方案才有效。
sixstatesaway 2012年

10

您可以使用#define这样的预处理器:

#define SYSTEM_VERSION_LESS_THAN(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

了解您的iOS版本。然后,我也可以使用以下代码来支持iOS 6:

NSString* addr = nil;
if (SYSTEM_VERSION_LESS_THAN(@"6.0")) {
   addr = [NSString stringWithFormat:@"http://maps.google.com/maps?daddr=%1.6f,%1.6f&saddr=Posizione attuale", view.annotation.coordinate.latitude,view.annotation.coordinate.longitude];
} else {
   addr = [NSString stringWithFormat:@"http://maps.apple.com/maps?daddr=%1.6f,%1.6f&saddr=Posizione attuale", view.annotation.coordinate.latitude,view.annotation.coordinate.longitude];
}

NSURL* url = [[NSURL alloc] initWithString:[addr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
[[UIApplication sharedApplication] openURL:url];

5

由于使用沙箱,您无权访问“地图”应用程序的书签。

而是使用“核心位置”自己确定当前位置。然后在您建立的URL中使用该位置(经纬度和经度)打开地图。


2
我看不到沙盒与要求Maps使用“当前位置”有什么关系。这是胡说八道。
grahamparks 2010年

3
我相信答案是指以下事实:“当前位置”位于“地图”应用程序的书签中,并且这些应用程序无权访问这些书签。废话少说,只是缺少那个联系。
James J

我怀疑仅在iPhone / iPod touch上使用“当前位置”(或URI编码的变体)就等于“不幸事故”,尽管它本身可以正常工作。(要说明的是I18N足以说服我-坚持坐标!)
Joe D'Andrea

4

我建议您查看CMMapLauncher,这是我创建的一个小型库,用于启动具有特定映射请求的Apple,Google和其他iOS映射应用程序。使用CMMapLauncher,获取问题中的路线的代码将是:

[CMMapLauncher launchMapApp:CMMapAppAppleMaps
          forDirectionsFrom:[CMMapPoint mapPointWithName:@"Origin"
                                              coordinate:myLatLong]
                         to:[CMMapPoint mapPointWithName:@"Destination"
                                              coordinate:latlong]];

如您所见,它还封装了iOS 6与其他版本之间所需的版本检查。


3

嘿,因为iOS6已经发布!

苹果在坏方面做得很出色(从我的角度来看)。

Apple的地图已启动,对于运行iOS 6的设备,maps.google.com/?q=如果要让iDevice打开本机Plan应用程序,则不应使用。现在是maps.apple.com/?q=

为了使开发人员不必进行太多工作,友好的maps.apple.com服务器将所有非Apple设备重定向到maps.google.com,因此更改是透明的。

通过这种方式,我们开发人员只需将所有Google查询字符串转换为Apple字符串即可。这是我非常讨厌的东西。

我今天必须实现这种功能,所以我做到了。但是我觉得我不应该只重写移动网站中的每个URL来定位到Apple的地图服务器,所以我认为我只是检测iDevices服务器端并为这些设备提供Apple URL。我以为我会分享。

我使用的是PHP,所以我使用了开源的Mobile Detect库:http : //code.google.com/p/php-mobile-detect/

只需将isiPad伪方法用作布尔型获取器就可以了,您将不会将google转换为苹果;-)

$server=$detect->isiPad()?"apple":"google";
$href="http://maps.{$server}.com/?q=..."

干杯!


2

您现在可以仅通过移动设备上的url以html格式执行此操作。这是一个例子。很酷的事情是,如果您将其转换为二维码,则可以通过某人通过在手机上扫描的方式,从任何地方获得指导。


2

真正的解决方案可以在这里找到。Z5 Concepts iOS开发代码段

它只需要一点编码。

- (IBAction)directions1_click:(id)sender
{
    NSString* address = @"118 Your Address., City, State, ZIPCODE";
    NSString* currentLocation = @"Current Location";
    NSString* url = [NSStringstringWithFormat: @"http://maps.google.com/maps?saddr=%@&daddr=%@",[currentLocation stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],[address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    UIApplication *app = [UIApplicationsharedApplication];
    [app openURL: [NSURL URLWithString: url]];
}

2

对于iOS6,Apple文档建议使用等效的maps.apple.com URL方案

所以用

http://maps.apple.com/maps?saddr=%f,%f&daddr=%f,%f

代替

http://maps.google.com/maps?saddr=%f,%f&daddr=%f,%f

向后兼容的代码将是

    NSString* versionNum = [[UIDevice currentDevice] systemVersion];
    NSString *nativeMapScheme = @"maps.apple.com";
    if ([versionNum compare:@"6.0" options:NSNumericSearch] == NSOrderedAscending)
        nativeMapScheme = @"maps.google.com";
    }
    NSString* url = [NSString stringWithFormat: @"http://%@/maps?saddr=%f,%f&daddr=%f,%f", nativeMapScheme
             startCoordinate.latitude, startCoordinate.longitude,
             endCoordinate.latitude, endCoordinate.longitude];
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];

Apple Maps URL方案包含其他全部受支持的参数:Apple URL方案参考

如果代码的其他部分中有条件代码,则可以使用这些iOS版本检测宏。iOS版本巨集


1
关于地图URL方案的不错的帖子,但是通常应该这样测试操作系统版本号。 systemVersion不是浮点数(例如5.1.1,不是浮点数),那么该比较实际上会产生错误的结果。
Nate 2012年

2

如果您不希望获得位置许可并且没有经纬度,请使用以下内容。

NSString *destinationAddress = @"Amsterdam";

Class itemClass = [MKMapItem class];
if (itemClass && [itemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)]) {

    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder geocodeAddressString:destinationAddress completionHandler:^(NSArray *placemarks, NSError *error) {
        if([placemarks count] > 0) {

            MKPlacemark *placeMark = [[MKPlacemark alloc] initWithPlacemark:[placemarks objectAtIndex:0]];

            MKMapItem *mapItem = [[MKMapItem alloc]initWithPlacemark:placeMark];

            MKMapItem *mapItem2 = [MKMapItem mapItemForCurrentLocation];


            NSArray *mapItems = @[mapItem, mapItem2];

            NSDictionary *options = @{
        MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,
        MKLaunchOptionsMapTypeKey:
            [NSNumber numberWithInteger:MKMapTypeStandard],
        MKLaunchOptionsShowsTrafficKey:@YES
            };

            [MKMapItem openMapsWithItems:mapItems launchOptions:options];

        } else {
            //error nothing found
        }
    }];
    return;
} else {

    NSString *sourceAddress = [LocalizedCurrentLocation currentLocationStringForCurrentLanguage];

    NSString *urlToOpen = [NSString stringWithFormat:@"http://maps.google.com/maps?saddr=%@&daddr=%@",
                 [sourceAddress stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
                 [destinationAddress stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlToOpen]];
}

对于ios5,“当前位置”必须使用正确的语言。我使用本文http://www.martip.net/blog/localized-current-location-string-for-iphone-apps中的LocalizedCurrentLocation

对于ios6,我使用CLGeocoder来获取地标,然后使用它和当前位置打开地图。

记住要添加CoreLocation.framework和MapKit.framework


1

对于iOS6 Maps App,您可以使用上面发布的相同网址 http://maps.google.com/maps?saddr=%f,%f&daddr=%@

但您使用的网址不是Google Maps URL,而是maps://显示以下网址:maps://saddr=%f,%f&daddr=%@.

使用“当前位置”似乎无效,因此我坚持使用坐标。

另一件好事:向后兼容:在iOS5上,它启动Google Maps应用程序。



1

我的建议是使用OpenInGoogleMaps-iOS因为这是最新的选择(到2015年11月),它支持可可豆荚的安装,您只需单击几下即可。

安装使用: pod "OpenInGoogleMaps"

在头文件中使用以下命令: #import "OpenInGoogleMapsController.h"

下面的示例代码:

/*In case the user does NOT have google maps, then apple maps shall open*/
[OpenInGoogleMapsController sharedInstance].fallbackStrategy = kGoogleMapsFallbackAppleMaps;    

/*Set the coordinates*/
GoogleMapDefinition *definition = [[GoogleMapDefinition alloc] init];   
CLLocationCoordinate2D metsovoMuseumCoords;     //coordinates struct
metsovoMuseumCoords.latitude = 39.770598;
metsovoMuseumCoords.longitude = 21.183215;
definition.zoomLevel = 20;
definition.center = metsovoMuseumCoords;        //this will be the center of the map

/*and here we open the map*/
[[OpenInGoogleMapsController sharedInstance] openMap:definition];       


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.