打开第三方地图进行导航

前言

  • App内根据手机上装载的地图App将其显示在弹出的选择框,选择对应地图跳转进入地图导航。需要用到- (BOOL)canOpenURL:(NSURL *)url NS_AVAILABLE_IOS(3_0);方法判断手机是否已安装相应地图App。
  • 要进行跳转需要先在xcode的plist文件内将目标App的url Scheme加入白名单(LSApplicationQueriesSchemes)。

常见第三方地图App的url Scheme

  • 百度地图:baidumap
  • 高德地图:iosamap
  • 谷歌地图:comgooglemaps (国内无法使用这个scheme检验)
  • 腾讯地图:qqmap

plist白名单设置

plist文件新增LSApplicationQueriesSchemes关键字,类型为NSArray,并在其下添加子目录,类型为NSString,内容为各地图对应的url Scheme。

![img](https:////upload-images.jianshu.io/upload_images/3820289-92f9f67b5106c0cb.png?imageMogr2/auto-orient/strip imageView2/2/w/486)

判断是否安装相应地图app

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
-(NSArray *)installedMapApp {
NSMutableArray *arr = [NSMutableArray array];
NSDictionary *dic;

//百度地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"map://"]]) {
    dic = @{
        @"key":@"origin",
        @"title":@"自带地图"
    };
    [arr addObject:dic];
}
  //百度地图
  if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"baidumap://"]]) {
      dic = @{
          @"key": @"baidumap",
          @"title":@"百度地图"
      };
      [arr addObject:dic];
  }

  //高德地图
  if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"iosamap://"]]) {
      dic = @{
          @"key": @"iosamap",
          @"title":@"高德地图"
      };
      [arr addObject:dic];
  }

  //谷歌地图
//      if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) {
//          dic = @{
//              @"key": @"comgooglemaps",
//              @"title":@"谷歌地图"
//          };
//          [arr addObject:dic];
//      }

  //腾讯地图
  if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"qqmap://"]]) {
      dic = @{
          @"key": @"qqmap",
          @"title":@"腾讯地图"
      };
      [arr addObject:dic];
  }
return arr;
}

使用对应的地图app打开并导航

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//google地图
-(void)naviByGoogleMap:(NavigationModel *)model{
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) {
  CLLocationCoordinate2D destination = [self geoExchangeBDGeoWith:model.userLocation];
  NSString* latitude =  [NSString stringWithFormat:@"%.f",destination.latitude];
  NSString* longitude = [NSString stringWithFormat:@"%.f",destination.longitude];
  NSString *urlString = [[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%@,%@&directionsmode=driving",@"导航测试",@"nav123456",latitude, longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString] options:@{} completionHandler:^(BOOL success) {
      
  }];
 }
}
//高德转百度
-(CLLocationCoordinate2D)geoExchangeBDGeoWith:(CLLocationCoordinate2D)location{
  double pi = 3.1415926535897932384626;
  double x = location.longitude;
  double y = location.latitude;
  double z = sqrt(x * x + y * y) + 0.00002 * sin(y * pi);
  double theta = atan2(y, x) + 0.000003 * cos(x * pi);
  double mgLon1 = z * cos(theta) + 0.0065;
  double mgLat1 = z * sin(theta) + 0.006;
  return CLLocationCoordinate2DMake(mgLat1, mgLon1);
}

//百度地图  https://lbsyun.baidu.com/index.php?title=uri/api/ios
-(void)naviByBaiduMap:(NavigationModel *)model{
CLLocationCoordinate2D destination = [self geoExchangeBDGeoWith:model.userLocation];
float latitude = destination.latitude;
float longitude = destination.longitude;
NSString *urlString = [NSString stringWithFormat:@"baidumap://map/direction?origin=latlng:%f,%f|name:我的位置&mode=transit&coord_type= bd09ll",model.userLocation.latitude, model.userLocation.longitude];
if (latitude != 0 && longitude != 0) {
    urlString = [NSString stringWithFormat:@"%@&destination=latlng:%f,%f|name:%@", urlString, latitude, longitude, model.toStr];
}else{
    urlString = [NSString stringWithFormat:@"%@&destination=%@|name:%@",urlString, model.toStr,model.toStr];
}
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlString]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString] options:@{} completionHandler:^(BOOL success) {
    
}];
}
}
//高德地图 https://lbs.amap.com/api/amap-mobile/guide/ios/route
-(void)naviByAMap:(NavigationModel *)model{
CLLocationCoordinate2D destination = model.destination;
float latitude = destination.latitude;
float longitude = destination.longitude;
NSString *urlString = [NSString stringWithFormat:@"iosamap://path?sourceApplication=臣小印&backScheme=cxy.shop.-saas.com&slat=%f&slon=%f&sname=我的位置&dev=0&t=1",model.userLocation.latitude, model.userLocation.longitude];
if (latitude != 0 && longitude != 0) {
    urlString = [NSString stringWithFormat:@"%@&dlat=%f&dlon=%f&dname=%@", urlString,latitude, longitude ,model.toStr];
}else{
    urlString = [NSString stringWithFormat:@"%@&dname=%@",urlString, model.toStr];
}
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlString]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString] options:@{} completionHandler:^(BOOL success) {
    
}];
}
}
//腾讯地图 https://lbs.qq.com/webApi/uriV1/uriGuide/uriMobileRoute
-(void)naviByQQMap:(NavigationModel *)model{
CLLocationCoordinate2D destination = model.destination;
float latitude = destination.latitude;
float longitude = destination.longitude;
NSString *urlString = [NSString stringWithFormat:@"qqmap://map/routeplan?type=walk&fromcoord=%f,%f&from=我的位置",model.userLocation.latitude, model.userLocation.longitude];
urlString = [NSString stringWithFormat:@"%@&tocoord=%f,%f&to=%@",urlString, latitude, longitude, model.toStr];
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:urlString]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString] options:@{} completionHandler:^(BOOL success) {
}];
}
}

//苹果原生地图
-(void)naviByAppleMap:(NavigationModel *)model {
CLLocationCoordinate2D desCoordinate = model.destination;
MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation];
currentLocation.name = model.fromStr ?  model.fromStr :  @"我的位置";
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:desCoordinate addressDictionary:nil]];
toLocation.name = model.toStr;

[MKMapItem openMapsWithItems:@[currentLocation, toLocation]
               launchOptions:@{MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeTransit,MKLaunchOptionsShowsTrafficKey: [NSNumber numberWithBool:YES]}];
}

/// 缩放地图到合适的区域,根据自己的位置和目的地计算出地图显示的最佳区域
/// @param antiLocation <#antiLocation description#>
- (void)fitRegion:(CLLocationCoordinate2D )antiLocation {
    CLLocationDegrees antiLatitude = antiLocation.latitude;
    CLLocationDegrees antiLongtitude = antiLocation.longitude;
    CLLocationDegrees userLatitude = self.mapView.userLocation.coordinate.latitude;
    CLLocationDegrees userLongtitude = self.mapView.userLocation.coordinate.longitude;
    //计算地图缩放的适当视口
    CLLocationCoordinate2D c2d = CLLocationCoordinate2DMake(userLatitude, userLongtitude);
    
    MACoordinateSpan span = MACoordinateSpanMake(fabs(antiLatitude - userLatitude), fabs(antiLongtitude - userLongtitude));
    MACoordinateRegion region = MACoordinateRegionMake(c2d, span);
    [self.mapView setRegion:region animated:true];
}

存在的问题:

  1. 苹果原生地图是可以卸载的, 但是没有合适的办法判断用户是否已经安装了原生的地图, 当用户没有安装时, 会有一个系统弹窗提示用户去app下载, 而且这个弹窗会弹两次,美团可大众点评都是如此,如有有解决办法请告知s