iOS开发之地图篇(二)


绿蚁新醅酒,红泥小火炉。
晚来天欲雪,能饮一杯无?

百度地图

1、注册地图api key

1
2
3
4
5
6
7
// 在程序启动代理方法注册baidu map api key 百度开发者平台获取
_mapManager = [[BMKMapManager alloc]init];
// 如果要关注网络及授权验证事件,请设定 generalDelegate参数
BOOL ret = [_mapManager start:XSBaiduMapApiKey generalDelegate:nil];
if (!ret) {
XSLog(@"BMKMapManager start failed!");
}

2、初始化地图

  • 添加地图的初始化配置
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
- (void)setupBaiduMapView
{
BMKMapView *mapView = [[BMKMapView alloc] initWithFrame:self.view.bounds];
mapView.mapType = BMKMapTypeStandard; // 设定为标准地图
mapView.showsUserLocation = YES;
mapView.userTrackingMode = BMKUserTrackingModeNone; // 设置用户位置图标类型
mapView.showMapScaleBar = YES;
BMKLocationViewDisplayParam *displayParam = [[BMKLocationViewDisplayParam alloc] init];
displayParam.locationViewImgName = @"icon_center_point";
displayParam.isAccuracyCircleShow = NO;
[mapView updateLocationViewWithParam:displayParam];// 配置用户位置信息如精度圈、图标
mapView.zoomLevel = kMapsZoomLevel;
mapView.minZoomLevel = kMapsMinZoomLevel;
mapView.maxZoomLevel = kMapsMaxZoomLevel;
[self.view insertSubview:mapView atIndex:0];
self.baiduMapView = mapView;
// 定位服务
BMKLocationService *locService = [[BMKLocationService alloc] init];
locService.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[locService startUserLocationService];
self.locService = locService;
// 反地理编码
BMKGeoCodeSearch *geoCodeSearch = [[BMKGeoCodeSearch alloc] init];
self.geoCodeSearch = geoCodeSearch;
// 针对切换地图类型后设置代理 (如果有做地图切换功能)
self.baiduMapView.delegate = self; // 此处记得不用的时候需要置nil,否则影响内存的释放
self.locService.delegate = self;
self.geoCodeSearch.delegate = self;
}

-(void)viewWillAppear:(BOOL)animated
{
[self.baiduMapView viewWillAppear];
self.baiduMapView.delegate = self; // 此处记得不用的时候需要置nil,否则影响内存的释放
self.locService.delegate = self;
self.geoCodeSearch.delegate = self;
}

-(void)viewWillDisappear:(BOOL)animated
{
[self.baiduMapView viewWillDisappear];
self.baiduMapView.delegate = nil; // 不用时,置nil
self.locService.delegate = nil;
self.geoCodeSearch.delegate = nil;
}
  • 开启定位服务回调,更新用户位置信息
1
2
3
4
5
6
7
8
9
10
11
-(void)didUpdateBMKUserLocation:(BMKUserLocation *)userLocation
{
XSLog(@"didUpdateBMKUserLocation位置 : %f,%f", userLocation.location.coordinate.latitude, userLocation.location.coordinate.longitude);
[self.baiduMapView updateLocationData:userLocation];
self.userBaiduLocation = userLocation;
}

- (void)didFailToLocateUserWithError:(NSError *)error
{
XSLog(@"error:%@", error);
}

3、显示自定义大头针

  • 3.1、从服务器获取当前设备的相关信息转为模型数据(XSDeviceLocation *locationDetails)
  • 3.2、根据当前显示的地图类型设置对应的坐标信息大头针

    • 我的做法在XSDeviceLocation模型里面提供了对应地图的获取属性,在属性getter方法中进行服务器的坐标转换(处理国内返回火星坐标、国外返回标准坐标)
    • 如获取百度坐标locationCoordinateBaidu、获取谷歌坐标locationCoordinateGoogle
    • 根据类型设置坐标数据

      1
      2
      3
      4
      5
      6
      - (void)setupPetLocationCoordinate:(CLLocationCoordinate2D)coordinate mapType:(XSDisplayMapType)mapType
      {
      // 坐标过滤等其他操作
      // ...
      [self setupBaiduMapCoordinate:coordinate];
      }
  • 3.3、根据设备坐标的相关配置

    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
    - (void)setupBaiduMapCoordinate:(CLLocationCoordinate2D)coordinate
    {
    [self.baiduMapView setCenterCoordinate:coordinate animated:YES];
    // 添加大头针模型数据
    self.pointAnnotation.annotationType = XSAnnotationTypeLocationPoint;
    self.pointAnnotation.locationDetailsModel = self.locationDetails;
    self.pointAnnotation.coordinate = coordinate;
    [self.baiduMapView addAnnotation:self.pointAnnotation];
    // 添加精度圈
    !self.baiduAccuracyCircle ? : [self.baiduMapView removeOverlay:self.baiduAccuracyCircle]; // 移除添加的精度圈
    if (self.locationDetails.GpsType == XSLocationModeWifiAndLbs || self.locationDetails.GpsType == XSLocationModeLbs) { // wifi 显示精度圈
    self.baiduAccuracyCircle = [BMKCircle circleWithCenterCoordinate:coordinate radius:self.locationDetails.Radius];
    [self.baiduMapView addOverlay:self.baiduAccuracyCircle];
    }
    // 解析地址
    BMKReverseGeoCodeOption *reverseGeocodeSearchOption = [[BMKReverseGeoCodeOption alloc] init];
    reverseGeocodeSearchOption.reverseGeoPoint = coordinate;
    if (![self.geoCodeSearch reverseGeoCode:reverseGeocodeSearchOption]) {
    XSLog(@"百度反地理编码获取地址失败");
    }
    // 计算地图区域缩放
    CLLocationDistance horizontalScreenDistance = [self horizontalScreenDistance];
    if (self.locationDetails.Radius * 2 < horizontalScreenDistance || self.baiduMapView.zoomLevel <= kMapsMinZoomLevel) {
    return;
    }
    BMKCoordinateRegion region = BMKCoordinateRegionMakeWithDistance(coordinate, self.locationDetails.Radius * 2 + self.locationDetails.Radius / 2, self.locationDetails.Radius * 2 + self.locationDetails.Radius / 2);
    [self.baiduMapView setRegion:region animated:YES];
    }
    • 自定义大头针模型XSPointAnnotation继承自BMKPointAnnotation

      • 扩充两个属性:
      • annotationType :枚举,显示的大头针类型(切换图标)
      • locationDetailsModel :当前大头针的模型数据,点击显示气泡详情的数据
    • 添加精度圈后精度半径过大可能超出屏幕影响用户体验,解决方法如下:

      • 根据屏幕最左和最后两个点,转换出地图上对应的坐标点并计算出距离d
      • 根据当前精度圈半径 * 2 和 d 比较,如果超出屏幕就重新设置地图显示区域
      • 计算屏幕距离核心代码

        1
        2
        3
        4
        5
        CLLocationCoordinate2D leftCoor = [self.baiduMapView convertPoint:CGPointMake(0, XSScreenH) toCoordinateFromView:self.view];
        CLLocationCoordinate2D rightCoor = [self.baiduMapView convertPoint:CGPointMake(XSScreenW, XSScreenH) toCoordinateFromView:self.view];
        BMKMapPoint pointLeft = BMKMapPointForCoordinate(leftCoor);
        BMKMapPoint pointRight = BMKMapPointForCoordinate(rightCoor);
        return BMKMetersBetweenMapPoints(pointLeft, pointRight);
  • 3.4、配置信息的回调(真正开始处理显示位置大头针、精度圈、点击显示的弹框泡泡)

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
// 大头针及大头针弹框
- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>)annotation
{
XSLogFunc
if (![annotation isKindOfClass:[XSPointAnnotation class]]) { // 不是自定义大头针模型
return nil;
}
BMKAnnotationView *annotationView = nil;
XSPointAnnotation *customAnnotation = (XSPointAnnotation *)annotation;
if (customAnnotation.annotationType == XSAnnotationTypeLocationPoint) { // 当前位置点类型
annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"LocationAnnotation"];
if (annotationView == nil) {
annotationView = [[BMKPinAnnotationView alloc] initWithAnnotation:customAnnotation reuseIdentifier:@"LocationAnnotation"];
}
annotationView.image = [UIImage imageNamed:self.locationDetails.deviceBindingTypeImageName];
annotationView.draggable = NO;
annotationView.canShowCallout = YES;
// 自定义的点击大头针显示的气泡View 根据公司需求自定义
self.petAnnotationView.locationDetails = customAnnotation.locationDetailsModel; // 需要显示的设备信息模型
self.petAnnotationView.isHiddenNoNeeds = NO;
self.petAnnotationView.width = 270;
annotationView.paopaoView = [[BMKActionPaopaoView alloc] initWithCustomView:self.petAnnotationView];
}
return annotationView;
}
// 精度圈
- (BMKOverlayView *)mapView:(BMKMapView *)mapView viewForOverlay:(id <BMKOverlay>)overlay
{
if ([overlay isKindOfClass:[BMKCircle class]]){
BMKCircleView *circleView = [[BMKCircleView alloc] initWithOverlay:overlay];
if (self.locationDetails.GpsType == XSLocationModeWifiAndLbs) {
circleView.fillColor = [[UIColor colorWithHexString:kAccuracyCircleWifiAndLbsFillColor] colorWithAlphaComponent:0.15];
circleView.strokeColor = [[UIColor colorWithHexString:kAccuracyCircleWifiAndLbsStrokeColor] colorWithAlphaComponent:0.05];
} else if (self.locationDetails.GpsType == XSLocationModeLbs) {
circleView.fillColor = [[UIColor colorWithHexString:kAccuracyCircleLbsFillColor] colorWithAlphaComponent:0.15];
circleView.strokeColor = [[UIColor colorWithHexString:kAccuracyCircleLbsStrokeColor] colorWithAlphaComponent:0.05];
}
circleView.lineWidth = 1;
return circleView;
}
return nil;
}
// 百度反地理编码解析地址回调,需要重新刷新大头针的气泡模型数据
- (void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKReverseGeoCodeResult *)result errorCode:(BMKSearchErrorCode)error
{
XSLog(@"address:%@----%@", result.addressDetail, result.address);
self.locationDetails.deviceAddress = result.address;
self.petAnnotationView.locationDetails = self.locationDetails;
}

4、多个坐标线显示在屏幕范围内

  • 绘制多个轨迹点和绘制线比较简单,直接参考官方文档
  • 在历史轨迹界面,可能希望显示的所有轨迹点都在屏幕范围内
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
- (void)baiduMapViewFitAnnotationsWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
{
NSMutableArray *latArr = [[NSMutableArray alloc] init];
NSMutableArray *lonArr = [[NSMutableArray alloc] init];
for (XSLocationDetails *locationDetails in coordsModels) {
[latArr addObject:@(locationDetails.coordinateBD09ll.latitude)];
[lonArr addObject:@(locationDetails.coordinateBD09ll.longitude)];
}
NSNumber *latMax = [latArr valueForKeyPath:@"@max.floatValue"];//最大纬度
NSNumber *latMin = [latArr valueForKeyPath:@"@min.floatValue"];//最小纬度
NSNumber *lonMax = [lonArr valueForKeyPath:@"@max.floatValue"];//最大经度
NSNumber *lonMin = [lonArr valueForKeyPath:@"@min.floatValue"];//最小经度

BMKCoordinateRegion region;
region.center.latitude = ([latMax doubleValue] + [latMin doubleValue]) / 2;
region.center.longitude = ([lonMax doubleValue] + [lonMin doubleValue]) / 2;
region.span.latitudeDelta = 0.0055; // 数字越小 缩放等级越大
region.span.longitudeDelta = 0.0055;
region = [self.baiduMapView regionThatFits:region];
[self.baiduMapView setRegion:region animated:YES];

// if (count < 2) return;
// CLLocationCoordinate2D coor = [coordsModels.firstObject coordinateBD09ll];
// BMKMapPoint pt = BMKMapPointForCoordinate(coor);
// CGFloat ltX, ltY, rbX, rbY;
// ltX = pt.x, ltY = pt.y;
// rbX = pt.x, rbY = pt.y;
//
// for (int i = 1; i < count; i++) {
// CLLocationCoordinate2D coor = [coordsModels[i] coordinateBD09ll];
// BMKMapPoint pt = BMKMapPointForCoordinate(coor);
// if (pt.x < ltX) ltX = pt.x;
// if (pt.x > rbX) rbX = pt.x;
// if (pt.y > ltY) ltY = pt.y;
// if (pt.y < rbY) rbY = pt.y;
// }
// BMKMapRect rect;
// rect.origin = BMKMapPointMake(ltX , ltY);
// rect.size = BMKMapSizeMake(rbX - ltX, rbY - ltY);
// [self.baiduMapView setVisibleMapRect:rect];
// self.baiduMapView.zoomLevel = self.baiduMapView.zoomLevel - 0.3;
}

谷歌地图

1、注册地图api key

1
2
// 在程序启动代理方法注册google map api key 谷歌开发者平台获取
[GMSServices provideAPIKey:kGoogleMapApiKey];

2、初始化地图

1
2
3
4
5
6
7
8
9
10
11
12
- (void)setupGoogleMapView
{
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:0 longitude:0 zoom:kMapsZoomLevel];
GMSMapView *mapView = [GMSMapView mapWithFrame:CGRectMake(0, 0, XSScreenW, XSScreenH) camera:camera];
mapView.delegate = self;
mapView.myLocationEnabled = YES;
[mapView setMinZoom:kMapsMinZoomLevel maxZoom:kMapsMaxZoomLevel];
mapView.settings.compassButton = YES;
mapView.settings.consumesGesturesInView = NO;
[self.view insertSubview:mapView atIndex:0];
self.googleMapView = mapView;
}

3、显示自定义大头针

  • 3.1、从服务器获取当前设备的相关信息转为模型数据(XSDeviceLocation *locationDetails)
  • 3.2、根据当前显示的地图类型设置对应的坐标信息大头针

    • 我的做法在XSDeviceLocation模型里面提供了对应地图的获取属性,在属性getter方法中进行服务器的坐标转换(处理国内返回火星坐标、国外返回标准坐标)
    • 如获取百度坐标locationCoordinateBaidu、获取谷歌坐标locationCoordinateGoogle
    • 根据类型设置坐标数据

      1
      2
      3
      4
      5
      6
      - (void)setupPetLocationCoordinate:(CLLocationCoordinate2D)coordinate mapType:(XSDisplayMapType)mapType
      {
      // 坐标过滤等其他操作
      // ...
      [self setupGoogleMapCoordinate:coordinate];
      }
  • 3.3、根据设备坐标的相关配置

    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
    - (void)setupGoogleMapCoordinate:(CLLocationCoordinate2D)coordinate
    {
    [self.googleMapView animateToLocation:coordinate];

    // Creates a marker in the center of the map.
    self.marker.markerType = XSMarkerTypeDefaultLocation;
    self.marker.position = coordinate;
    self.marker.appearAnimation = YES;
    self.marker.tracksInfoWindowChanges = YES;
    self.marker.icon = [UIImage imageNamed:self.locationDetails.deviceBindingTypeImageName];
    self.marker.map = self.googleMapView;
    self.marker.locationDetailsModel = self.locationDetails; // 传递模型数据
    // 点击大头针显示的自定义气泡控件 懒加载
    self.petAnnotationView.locationDetails = self.locationDetails;
    self.petAnnotationView.isHiddenNoNeeds = NO;

    [[GMSGeocoder geocoder] reverseGeocodeCoordinate:coordinate completionHandler:^(GMSReverseGeocodeResponse * _Nullable response, NSError * _Nullable error) {

    //FIXME: 错误信息处理

    // 获取第一个位置信息
    GMSAddress *addressModel = response.firstResult;
    NSString *firstString = addressModel.lines.firstObject;
    NSString *lastString = addressModel.lines.lastObject;
    NSString *address = [NSString stringWithFormat:@"%@, %@", firstString, lastString];
    self.locationDetails.deviceAddress = address;

    self.marker.locationDetailsModel = self.locationDetails; // 传递模型数据
    self.petAnnotationView.locationDetails = self.locationDetails;
    }];
    // 添加精度圈
    self.googleAccuracycircle.map = nil; // 清空已存在的
    if (self.locationDetails.GpsType == XSLocationModeWifiAndLbs) { // wifi 显示精度圈
    self.googleAccuracycircle = [GMSCircle circleWithPosition:coordinate radius:self.locationDetails.Radius];
    self.googleAccuracycircle.fillColor = [[UIColor colorWithHexString:kAccuracyCircleWifiAndLbsFillColor] colorWithAlphaComponent:0.15];
    self.googleAccuracycircle.strokeColor = [[UIColor colorWithHexString:kAccuracyCircleWifiAndLbsStrokeColor] colorWithAlphaComponent:0.15];
    self.googleAccuracycircle.strokeWidth = 1;
    self.googleAccuracycircle.map = self.googleMapView;
    } else if (self.locationDetails.GpsType == XSLocationModeLbs) {
    self.googleAccuracycircle = [GMSCircle circleWithPosition:coordinate radius:self.locationDetails.Radius];
    self.googleAccuracycircle.fillColor = [[UIColor colorWithHexString:kAccuracyCircleLbsFillColor] colorWithAlphaComponent:0.15];
    self.googleAccuracycircle.strokeColor = [[UIColor colorWithHexString:kAccuracyCircleLbsStrokeColor] colorWithAlphaComponent:0.15];
    self.googleAccuracycircle.strokeWidth = 1;
    self.googleAccuracycircle.map = self.googleMapView;
    }

    // 计算地图区域缩放
    CLLocationDistance horizontalScreenDistance = [self horizontalScreenDistance];
    if (self.locationDetails.Radius * 2 < horizontalScreenDistance || self.googleMapView.camera.zoom <= kMapsMinZoomLevel) {
    return;
    }
    int zoomLevel = self.googleMapView.camera.zoom;
    // double radius = self.locationDetails.Radius + self.locationDetails.Radius / 2;
    double radius = self.locationDetails.Radius / 2;
    double scale = radius / 500;
    zoomLevel = (int) (16 - log(scale) / log(2));
    zoomLevel--;

    [CATransaction begin];
    [CATransaction setValue:[NSNumber numberWithFloat:XSAnimationDuration] forKey:kCATransactionAnimationDuration];
    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:coordinate.latitude longitude:coordinate.longitude zoom:zoomLevel];
    [self.googleMapView animateToCameraPosition:camera];
    [CATransaction commit];
    }
    • 自定义大头针模型XSMarker继承自GMSMarker

      • 扩充两个属性:
      • markerType :枚举,显示的大头针类型(切换图标)
      • locationDetailsModel :当前大头针的模型数据,点击显示气泡详情的数据
    • 添加精度圈后精度半径过大可能超出屏幕影响用户体验,解决方法如下:

      • 根据屏幕最左和最后两个点,转换出地图上对应的坐标点并计算出距离d
      • 根据当前精度圈半径 * 2 和 d 比较,如果超出屏幕就重新设置地图显示区域
      • 计算屏幕距离核心代码

        1
        2
        3
        CLLocationCoordinate2D leftCoor = [self.googleMapView.projection coordinateForPoint:CGPointMake(0, XSScreenH)];
        CLLocationCoordinate2D rightCoor = [self.googleMapView.projection coordinateForPoint:CGPointMake(XSScreenW, XSScreenH)];
        return GMSGeometryDistance(leftCoor, rightCoor);
  • 3.4、点击大头针显示气泡view的回调

1
2
3
4
5
6
7
- (UIView *)mapView:(GMSMapView *)mapView markerInfoWindow:(GMSMarker *)marker
{
XSLogFunc
self.petAnnotationView.width = 270;
self.petAnnotationView.locationDetails = self.locationDetails; // 刷新显示的信息
return self.petAnnotationView;
}

4、多个坐标线显示在屏幕范围内

  • 绘制多个轨迹点和绘制线比较简单,直接参考官方文档
  • 在历史轨迹界面,可能希望显示的所有轨迹点都在屏幕范围内
1
2
3
4
5
6
7
8
9
- (void)googleMapViewFitAnnotationsWithCoordinates:(NSArray *)coordsModels count:(NSUInteger)count
{
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] init];
for (int i = 1; i < count; i++) {
CLLocationCoordinate2D coor = [coordsModels[i] locationCoordinate2D];
bounds = [bounds includingCoordinate:coor];
}
[self.googleMapView animateWithCameraUpdate:[GMSCameraUpdate fitBounds:bounds withPadding:30.0f]];
}

Maps 导航

  • 检测是否安装对应的地图
  • 常用的4个地图的 URL Scheme:

    1.苹果自带地图(不需要检测,所以不需要URL Scheme)
    2.百度地图 :baidumap://
    3.高德地图 :iosamap://
    4.谷歌地图 :comgooglemaps://

  • 在IOS9之后,苹果进一步完善了安全机制,必须在plist里面设置url scheme白名单,不然无法打开对应的应用
  • 添加白名单:

在 info.plist 文件里面,添加一个字段:LSApplicationQueriesSchemes,类型为数组

然后在这个数组里面再添加我们所需要的地图 URL Scheme :

1
2
3
4
> baidumap // 百度
> iosamap // 高德
> comgooglemaps // 谷歌
>
  • 应用内部调用google maps地图发起导航功能

1、x-source=%@&x-success=%@跟高德一样 这里分别代表APP的名称和URL Scheme

2、saddr=这里留空则表示从当前位置触发。

1
2
3
4
5
6
7
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) {
NSMutableDictionary *googleMapDic = [NSMutableDictionary dictionary];
googleMapDic[@"title"] = @"谷歌地图";
NSString *urlString = [[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%f,%f&directionsmode=driving",@"导航测试",@"nav123456",endLocation.latitude, endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
googleMapDic[@"url"] = urlString;
[maps addObject:googleMapDic];
}
  • 应用内部调用百度地图发起导航功能

1,origin=, 这个是不能被修改的,不然无法把出发位置设置为当前位置

2,destination = latlng:%f,%f|name = 目的地这里面的 name 的字段不能省略,否则导航会失败,而后面的文字则可以随意,赋个你的目的地的值给他就可以了。

3,coord_type = gcj02coord_type 允许的值为 bd09ll、gcj02、wgs84,如果你 APP 的地图 SDK 用的是百度地图 SDK,请填 bd09ll,否则就填gcj02,wgs84的话基本是用不上了

1
2
3
4
5
6
7
if ([[UIApplication sharedApplication] canOpenURL:[NSURL        URLWithString:@"baidumap://"]]) {
NSMutableDictionary *baiduMapDic = [NSMutableDictionary dictionary];
baiduMapDic[@"title"] = @"百度地图";
NSString *urlString = [[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=latlng:%f,%f|name=北京&mode=driving&coord_type=gcj02",endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
baiduMapDic[@"url"] = urlString;
[maps addObject:baiduMapDic];
}
  • 应用内部调用高德地图发起导航功能

1、sourceApplication=%@&backScheme=%@sourceApplication代表你自己APP的名称 会在之后跳回的时候显示出来 所以必须填写 backScheme是你APP的URL Scheme 不填是跳不回来的哟

2、dev=0这里填0就行了,跟上面的gcj02一个意思 1代表wgs84 也用不上

1
2
3
4
5
6
7
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"iosamap://"]]) {
NSMutableDictionary *gaodeMapDic = [NSMutableDictionary dictionary];
gaodeMapDic[@"title"] = @"高德地图";
NSString *urlString = [[NSString stringWithFormat:@"iosamap://navi?sourceApplication=%@&backScheme=%@&lat=%f&lon=%f&dev=0&style=2",@"导航功能",@"nav123456",endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
gaodeMapDic[@"url"] = urlString;
[maps addObject:gaodeMapDic];
}
  • 应用内部调用苹果地图发起导航功能
1
2
3
4
5
6
CLLocationCoordinate2D loc = CLLocationCoordinate2DMake([self.model.latitude floatValue], [self.model.longitude floatValue]);
MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation];
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:loc addressDictionary:nil]];
[MKMapItem openMapsWithItems:@[currentLocation, toLocation]
launchOptions:@{MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsShowsTrafficKey: [NSNumber numberWithBool:YES]}];
要不要鼓励一下😘