iOS - MKMapView 地图

简介: 1、创建 MKMapView 地图在 iOS6 或者 iOS7 中实现这个功能只需要添加地图控件、设置用户跟踪模式、在 mapView:didUpdateUserLocation: 代理方法中设置地图中心区域及显示范围。

1、创建 MKMapView 地图

  • 在 iOS6 或者 iOS7 中实现这个功能只需要添加地图控件、设置用户跟踪模式、在 mapView:didUpdateUserLocation: 代理方法中设置地图中心区域及显示范围。
  • 在 iOS8+ 中用法稍有不同:
    • a. 由于在地图中进行用户位置跟踪需要使用定位功能,而定位功能在 iOS8 中设计发生了变化,因此必须按照定位中提到的内容进行配置和请求。
    • b. iOS8+ 中不需要进行中心点的指定,默认会将当前位置设置中心点并自动设置显示区域范围。
        // 包含头文件
        #import <CoreLocation/CoreLocation.h>
        #import <MapKit/MapKit.h>
    
        // 遵守协议
        <MKMapViewDelegate, CLLocationManagerDelegate>
    
        // 声明地图控件
        @property (nonatomic, strong) MKMapView *mapView;
  • 1、请求定位

        // 实例化定位管理器
        CLLocationManager *locationManager = [[CLLocationManager alloc] init];
        locationManager.delegate = self;
    
        // 判断系统定位服务是否开启
        if (![CLLocationManager locationServicesEnabled]) {
    
            NSLog(@"%@", @"提示:系统定位服务不可用,请开启 !");
    
        } else {
    
            // 判断应用定位服务授权状态
            if([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){                 // 没有授权
    
                // 8.0 及以上系统需手动请求定位授权
                if ([UIDevice currentDevice].systemVersion.doubleValue >= 8.0) {
    
                    // 前台定位,需在 info.plist 里设置 Privacy - Location When In Use Usage Description 的值
                    [locationManager requestWhenInUseAuthorization];
    
                    // 前后台同时定位,需在 info.plist 里设置 Privacy - Location Always Usage Description 的值
                    // [self.locationManager requestAlwaysAuthorization];
                }
    
                // 开始定位追踪(第一次打开软件时)
                [locationManager startUpdatingLocation];
    
            } else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse
                       || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways) {  // 允许定位授权
    
                // 开始定位追踪
                [locationManager startUpdatingLocation];
    
            } else{                                                                                             // 拒绝定位授权
    
                // 创建警告框(自定义方法)
                NSLog(@"%@", @"提示:当前应用的定位服务不可用,请检查定位服务授权状态 !");
            }
        }
  • 2、创建地图

        /*
            mapType:
    
                MKMapTypeStandard = 0,                标准类型
                MKMapTypeSatellite,                   卫星图
                MKMapTypeHybrid                       混合类型
    
            userTrackingMode:用户位置追踪用于标记用户当前位置,此时会调用定位服务,必须先设置定位请求
    
                MKUserTrackingModeNone = 0,           不跟踪用户位置
                MKUserTrackingModeFollow,             跟踪并在地图上显示用户的当前位置
                MKUserTrackingModeFollowWithHeading,  跟踪并在地图上显示用户的当前位置,地图会跟随用户的前进方向进行旋转
         */
    
        // 实例化地图控件
        self.mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
        self.mapView.delegate = self;
    
        // 设置地图类型
        self.mapView.mapType = MKMapTypeStandard;
    
        // 设置跟踪模式
        self.mapView.userTrackingMode = MKUserTrackingModeFollow;
    
        [self.view addSubview:self.mapView];
        #pragma mark - MKMapViewDelegate 协议方法
    
        // 更新到用户的位置
        - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
    
            // 只要用户位置改变就调用此方法(包括第一次定位到用户位置),userLocation:是对用来显示用户位置的蓝色大头针的封装
    
            // 反地理编码
            [[[CLGeocoder alloc] init] reverseGeocodeLocation:userLocation.location
                                            completionHandler:^(NSArray *placemarks, NSError *error) {
    
                CLPlacemark *placemark = [placemarks firstObject];
    
                // 设置用户位置蓝色大头针的标题
                userLocation.title = [NSString stringWithFormat:@"当前位置:%@, %@, %@",
                                      placemark.thoroughfare, placemark.locality, placemark.country];
            }];
    
            // 设置用户位置蓝色大头针的副标题
            userLocation.subtitle = [NSString stringWithFormat:@"经纬度:(%lf, %lf)",
                                     userLocation.location.coordinate.longitude, userLocation.location.coordinate.latitude];
    
            // 手动设置显示区域中心点和范围
    
            if ([UIDevice currentDevice].systemVersion.floatValue < 8.0) {
    
                // 显示的中心
                CLLocationCoordinate2D center = userLocation.location.coordinate;
    
                // 设置地图显示的中心点
                [self.mapView setCenterCoordinate:center animated:YES];
    
                // 设置地图显示的经纬度跨度
                MKCoordinateSpan span = MKCoordinateSpanMake(0.023503, 0.017424);
    
                // 设置地图显示的范围
                MKCoordinateRegion rengion = MKCoordinateRegionMake(center, span);
                [self.mapView setRegion:rengion animated:YES];
            }
        }
    
        // 地图显示的区域将要改变
        - (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated {
    
            NSLog(@"区域将要改变:经度:%lf, 纬度:%lf, 经度跨度:%lf, 纬度跨度:%lf",
                  mapView.region.center.longitude, mapView.region.center.latitude,
                  mapView.region.span.longitudeDelta, mapView.region.span.latitudeDelta);
        }
    
        // 地图显示的区域改变了
        - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    
            NSLog(@"区域已经改变:经度:%lf, 纬度:%lf, 经度跨度:%lf, 纬度跨度:%lf",
                  mapView.region.center.longitude, mapView.region.center.latitude,
                  mapView.region.span.longitudeDelta, mapView.region.span.latitudeDelta);
        }
  • 效果

    mkmapview1mkmapview2

2、添加大头针

2.1 添加大头针

  • 自定义大头针模型

    • QAnnotation.h

          #import <MapKit/MapKit.h>
      
          @interface QAnnotation : NSObject <MKAnnotation>
      
          @property (nonatomic, copy)NSString *title;
          @property (nonatomic, copy)NSString *subtitle;
          @property (nonatomic, copy)NSString *icon;
          @property (nonatomic, assign)CLLocationCoordinate2D coordinate;
      
          /// 初始化大头针模型
          + (instancetype)q_annotationWithTitle:(NSString *)title
                                       subTitle:(NSString *)subTitle
                                           icon:(NSString *)icon
                                     coordinate:(CLLocationCoordinate2D)coordinate;
      
          @end
    • QAnnotation.m

          @implementation QAnnotation
      
          /// 初始化大头针模型
          + (instancetype)q_annotationWithTitle:(NSString *)title
                                       subTitle:(NSString *)subTitle
                                           icon:(NSString *)icon
                                     coordinate:(CLLocationCoordinate2D)coordinate{
      
              QAnnotation *annotation = [[self alloc] init];
      
              annotation.title = title;
              annotation.subtitle = subTitle;
              annotation.icon = icon;
              annotation.coordinate = coordinate;
      
              return annotation;
          }
      
          @end
  • 添加大头针

    • ViewController.m

          #import "QAnnotation.h"
      
          // 首先创建 MKMapView 地图
      
          // 设置大头针显示的内容
          NSString *title = @"xxx大饭店";
          NSString *subtitle = @"全场一律15折,会员20折";
          NSString *icon = @"category_1";
      
          // 设置大头针放置的位置
          CLLocationCoordinate2D cl2d = CLLocationCoordinate2DMake(40.1020, 116.3265);
      
          // 初始化大头针模型
          QAnnotation *annotation = [QAnnotation q_annotationWithTitle:title
                                                              subTitle:subtitle
                                                                  icon:icon
                                                            coordinate:cl2d];
      
          // 在地图上添加大头针控件
          [self.mapView addAnnotation:annotation];
    • 效果

      mkmapview3mkmapview4

2.2 设置大头针样式

  • 设置大头针样式

        // MKMapViewDelegate 协议方法
        - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
    
            /*
                显示大头针时触发,返回大头针视图,通常自定义大头针可以通过此方法进行。
                使用遵守协议 <MKAnnotation> 的模型,写此方法时所有遵守协议 <MKAnnotation> 的大头针模型都会改变,不写时为默认样式的大头针。
             */
    
            // 判断大头针模型是否属于 QAnnotation 类
            if ([annotation isKindOfClass:[QAnnotation class]]) {
    
                // 显示自定义样式的大头针
    
                // 获得大头针控件,利用自定义的( QAnnotationView )大头针控件创建
                QAnnotationView *annotationView = [QAnnotationView q_annotationViewWithMapView:mapView];
    
                // 传递模型,更新大头针数据,覆盖掉之前的旧数据
                annotationView.annotation = annotation;
    
                return annotationView;
    
            } else {
    
                // 显示系统样式的大头针
    
                // 先从缓存池中取出可以循环利用的大头针控件,利用带针的( MKPinAnnotationView )子类大头针控件创建
                MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"qianchia"];
    
                // 缓存池中没有可以利用的大头针控件
                if (annotationView == nil) {
    
                    // 创建大头针控件
                    annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@"qianchia"];
    
                    // 设置大头针头的颜色
                    annotationView.pinColor = MKPinAnnotationColorGreen;
    
                    // 大头针从天而降
                    annotationView.animatesDrop = YES;
    
                    // 显示大头针标题和子标题
                    annotationView.canShowCallout = YES;
    
                    // 设置子菜单的偏移量
                    annotationView.calloutOffset = CGPointMake(0, -10);
    
                    // 自定义子菜单的左右视图
                    annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
                    annotationView.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeInfoDark];
                }
    
                // 传递模型,更新大头针数据,覆盖掉之前的旧数据
                annotationView.annotation = annotation;
    
                return annotationView;
            }
        }
  • 效果

    mkmapview5mkmapview6

    mkmapview7mkmapview8

2.3 不同大头针样式的创建

  • 1、带针的大头针

        // 先从缓存池中取出可以循环利用的大头针控件,利用带针的( MKPinAnnotationView )子类大头针控件创建
        MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"qianchia"];
    
        // 缓存池中没有可以利用的大头针控件
        if (annotationView == nil) {
    
            // 创建大头针控件
            annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@"qianchia"];
    
            // 设置大头针头的颜色
            annotationView.pinColor = MKPinAnnotationColorGreen;
    
            // 大头针从天而降
            annotationView.animatesDrop = YES;
    
            // 显示大头针标题和子标题
            annotationView.canShowCallout = YES;
    
            // 设置子菜单的偏移量
            annotationView.calloutOffset = CGPointMake(0, -10);
    
            // 自定义子菜单的左右视图
            annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
            annotationView.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeInfoDark];
        }
    
        // 传递模型,更新大头针数据,覆盖掉之前的旧数据
        annotationView.annotation = annotation;
    
        return annotationView;
    • 效果

      mkmapview9mkmapview10

  • 2、不带针的大头针

        // 先从缓存池中取出可以循环利用的大头针控件 利用不带针的( MKAnnotationView )父类大头针控件创建
        MKAnnotationView *annotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"qianchia"];
    
        // 缓存池中没有可以利用的大头针控件
        if (annotationView == nil) {
    
            // 创建大头针控件
            annotationView = [[MKAnnotationView alloc] initWithAnnotation:nil reuseIdentifier:@"qianchia"];
    
            // 显示大头针标题和子标题
            annotationView.canShowCallout = YES;
    
            // 设置子菜单的偏移量
            annotationView.calloutOffset = CGPointMake(0, -10);
    
            // 自定义子菜单的左右视图
            annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
            annotationView.leftCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeInfoDark];
        }
    
        // 传递模型,更新大头针数据,覆盖掉之前的旧数据
        annotationView.annotation = annotation;
    
        // 设置大头针的图片,所有大头针图片相同
        annotationView.image = [UIImage imageNamed:@"category_4"];
    
        return annotationView;
    • 效果

      mkmapview11mkmapview12

  • 3、自定义类型的大头针

    • QAnnotationView.h

          @interface QAnnotationView : MKAnnotationView
      
          /// 创建大头针控件
          + (instancetype)q_annotationViewWithMapView:(MKMapView *)mapView;
      
          @end
    • QAnnotationView.m

          #import "QAnnotation.h"
          #import "UIView+Frame.h"
      
          @interface QAnnotationView ()
      
          /// 自定义大头针子菜单图片视图
          @property (nonatomic, strong) UIImageView *iconView;
      
          @end
      
          @implementation QAnnotationView
      
          #pragma mark - 创建大头针控件
      
          /// 创建大头针控件
          + (instancetype)q_annotationViewWithMapView:(MKMapView *)mapView {
      
              QAnnotationView *annotationView = (QAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"qianchia"];
      
              if (annotationView == nil) {
      
                  annotationView = [[self alloc] initWithAnnotation:nil reuseIdentifier:@"qianchia"];
              }
      
              return annotationView;
          }
      
          /// 重写初始化大头针控件方法
          - (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
      
              if (self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {
      
                  // 显示自定义大头针的标题和子标题
                  self.canShowCallout = YES;
      
                  // 设置自定义大头针的子菜单左边显示一个图片
                  UIImageView *imageView = [[UIImageView alloc] init];
                  imageView.bounds = CGRectMake(0, 0, 40, 50);
                  self.iconView = imageView;
      
                  // 设置自定义大头针的子菜单左边视图
                  self.leftCalloutAccessoryView = self.iconView;
              }
              return self;
          }
      
          /// 重写大头针模型的 setter 方法
          - (void)setAnnotation:(QAnnotation *)annotation{
      
              [super setAnnotation:annotation];
      
              // 设置自定义大头针图片
              self.image = [UIImage imageNamed:annotation.icon];
      
              // 设置自定义大头针的子菜单图片
              self.iconView.image = [UIImage imageNamed:annotation.icon];
          }
      
          @end
    • ViewController.m

          // 判断大头针模型是否属于 QAnnotation 类
          if ([annotation isKindOfClass:[QAnnotation class]]) {
      
              // 获得大头针控件,利用自定义的( QAnnotationView )大头针控件创建
              QAnnotationView *annotationView = [QAnnotationView q_annotationViewWithMapView:mapView];
      
              // 传递模型,更新大头针数据,覆盖掉之前的旧数据
              annotationView.annotation = annotation;
      
              return annotationView;
          }
    • 效果

      mkmapview13mkmapview14

3、地图画线

  • 设置起点和终点

        // 获取起点和终点
        NSString *sourceAddress = [alertView textFieldAtIndex:0].text;
        NSString *destinationAddress = [alertView textFieldAtIndex:1].text;
    
        // 地理编码 起点
        [[[CLGeocoder alloc] init] geocodeAddressString:sourceAddress completionHandler:^(NSArray *placemarks, NSError *error) {
    
            if (placemarks == nil || error) {
                return;
            } else {
    
                CLPlacemark *sourcePlacemark = [placemarks firstObject];
    
                // 移除以前的大头针
                if (self.sourceAnnotation) {
                    [self.mapView removeAnnotation:self.sourceAnnotation];
                }
    
                // 添加新的大头针
                self.sourceAnnotation = [QAnnotation q_annotationWithTitle:sourceAddress
                                                                  subTitle:sourcePlacemark.name
                                                                      icon:nil
                                                                coordinate:sourcePlacemark.location.coordinate];
                [self.mapView addAnnotation:self.sourceAnnotation];
    
                // 地理编码 终点
                [[[CLGeocoder alloc] init] geocodeAddressString:destinationAddress completionHandler:^(NSArray *placemarks, NSError *error) {
    
                    if (placemarks == nil || error) {
                        return;
                    } else {
    
                        CLPlacemark *destinationPlacemark = [placemarks firstObject];
    
                        // 移除以前的大头针
                        if (self.destinationAnnotation) {
                            [self.mapView removeAnnotation:self.destinationAnnotation];
                        }
    
                        // 添加新的大头针
                        self.destinationAnnotation = [QAnnotation q_annotationWithTitle:destinationAddress
                                                                               subTitle:destinationPlacemark.name
                                                                                   icon:nil
                                                                             coordinate:destinationPlacemark.location.coordinate];
                        [self.mapView addAnnotation:self.destinationAnnotation];
    
                        // 开始画线
                        [self drawLineWithSourceCLPlacemark:sourcePlacemark destinationCLPlacemark:destinationPlacemark];
                    }
                }];
            }
        }];
  • 开始画线

        // 自定义方法
        - (void)drawLineWithSourceCLPlacemark:(CLPlacemark *)sourceCLPm destinationCLPlacemark:(CLPlacemark *)desinationCLPm{
    
            // 初始化方向请求
            MKDirectionsRequest *dRequest = [[MKDirectionsRequest alloc] init];
    
            // 设置起点( CLPlacemark --> MKPlacemark )
            MKPlacemark *sourceMKPm = [[MKPlacemark alloc] initWithPlacemark:sourceCLPm];
            dRequest.source = [[MKMapItem alloc] initWithPlacemark:sourceMKPm];
    
            // 设置终点( CLPlacemark --> MKPlacemark )
            MKPlacemark *destinationMKPm = [[MKPlacemark alloc] initWithPlacemark:desinationCLPm];
            dRequest.destination = [[MKMapItem alloc] initWithPlacemark:destinationMKPm];
    
            // 根据请求创建方向
            MKDirections *directions = [[MKDirections alloc] initWithRequest:dRequest];
    
            // 执行请求
            [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
    
                if (error) {
                    return;
                } else {
    
                    // 移除所有已画的线,移除旧的线
                    [self.mapView removeOverlays:self.mapView.overlays];
    
                    for (MKRoute *route in response.routes) {
    
                        // 添加路线,传递路线的遮盖模型数据
                        [self.mapView addOverlay:route.polyline];
                    }
                }
            }];
        }
  • 设置画线属性

        // MKMapViewDelegate 协议方法
        - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
    
            MKPolylineRenderer *rederer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
    
            rederer.lineWidth = 5;                          // 设置线宽
            rederer.strokeColor = [UIColor blueColor];      // 设置线的颜色
    
            return rederer;
        }
  • 效果

    mkmapview15mkmapview16

    mkmapview17mkmapview18

4、地图导航

4.1 创建导航

  • 设置起点和终点

        // 获取起点和终点
        NSString *sourceAddress = [alertView textFieldAtIndex:0].text;
        NSString *destinationAddress = [alertView textFieldAtIndex:1].text;
    
        // 地理编码 起点
        [[[CLGeocoder alloc] init] geocodeAddressString:sourceAddress completionHandler:^(NSArray *placemarks, NSError *error) {
    
            if (placemarks == nil || error) {
                return;
            } else {
    
                CLPlacemark *sourcePlacemark = [placemarks firstObject];
    
                // 地理编码 终点
                [[[CLGeocoder alloc] init] geocodeAddressString:destinationAddress completionHandler:^(NSArray *placemarks, NSError *error) {
    
                    if (placemarks == nil || error) {
                        return;
                    } else {
    
                        CLPlacemark *destinationPlacemark = [placemarks firstObject];
    
                        // 开始导航
                        [self startNavigationWithSourceCLPlacemark:sourcePlacemark destinationCLPlacemark:destinationPlacemark];
                    }
                }];
            }
        }];
  • 开始导航

        设置导航参数:
    
            MKLaunchOptionsDirectionsModeKey           // 导航模式     Key to a directions mode
            MKLaunchOptionsMapTypeKey                  // 地图类型     Key to an NSNumber corresponding to a MKMapType
            MKLaunchOptionsShowsTrafficKey             // 交通路况     Key to a boolean NSNumber
    
            // Directions modes
            MKLaunchOptionsDirectionsModeDriving       // 驾驶模式
            MKLaunchOptionsDirectionsModeWalking       // 步行模式
    
            // If center and span are present, having a camera as well is undefined
            MKLaunchOptionsMapCenterKey                // 地图中心     Key to an NSValue-encoded CLLocationCoordinate2D
            MKLaunchOptionsMapSpanKey                  // 地图跨度     Key to an NSValue-encoded MKCoordinateSpan
            MKLaunchOptionsCameraKey                   // 地图相机     Key to MKMapCamera object
        // 自定义方法
        - (void)startNavigationWithSourceCLPlacemark:(CLPlacemark *)sourceCLPm destinationCLPlacemark:(CLPlacemark *)desinationCLPm{
    
            if (sourceCLPm == nil || desinationCLPm == nil) {
                return;
            } else {
    
                // 设置起点( CLPlacemark --> MKPlacemark )
                MKPlacemark *sourceMKPm = [[MKPlacemark alloc] initWithPlacemark:sourceCLPm];
                MKMapItem *sourceItem = [[MKMapItem alloc] initWithPlacemark:sourceMKPm];
    
                // 设置终点( CLPlacemark --> MKPlacemark )
                MKPlacemark *destinationMKPm = [[MKPlacemark alloc] initWithPlacemark:desinationCLPm];
                MKMapItem *destinationItem = [[MKMapItem alloc] initWithPlacemark:destinationMKPm];
    
                NSArray *items = @[sourceItem, destinationItem];
    
                // 设置导航参数(导航模式:驾驶导航,是否显示路况:是,地图类型:标准)
                NSDictionary *options = @{MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving,
                                            MKLaunchOptionsShowsTrafficKey: @YES,
                                                 MKLaunchOptionsMapTypeKey: @(MKMapTypeStandard)};
    
                // 打开苹果官方的导航应用(打开苹果自带地图 App 开始导航)
                [MKMapItem openMapsWithItems:items launchOptions:options];
            }
        }
  • 效果

    mkmapview19mkmapview27

    mkmapview28mkmapview20

4.2 快速创建导航

  • 从当前位置到指定位置导航

        // 根据“北京市”进行地理编码
        [_geocoder geocodeAddressString:@"北京市" completionHandler:^(NSArray *placemarks, NSError *error) {
    
            CLPlacemark *clPlacemark = [placemarks firstObject];                            // 获取第一个地标
            MKPlacemark *mkplacemark = [[MKPlacemark alloc] initWithPlacemark:clPlacemark]; // 定位地标转化为地图的地标
    
            NSDictionary *options = @{MKLaunchOptionsMapTypeKey:@(MKMapTypeStandard)};
            MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:mkplacemark];
    
            // 调用苹果地图开始导航,从当前位置到指定位置
            [mapItem openInMapsWithLaunchOptions:options];
        }];
    • 效果

      mkmapview21mkmapview22

  • 从位置 1 到位置 2 导航

        // 根据“北京市”进行地理编码
        [_geocoder geocodeAddressString:@"北京市" completionHandler:^(NSArray *placemarks, NSError *error) {
    
            CLPlacemark *clPlacemark1 = [placemarks firstObject];
            MKPlacemark *mkPlacemark1 = [[MKPlacemark alloc] initWithPlacemark:clPlacemark1];
    
            // 注意地理编码一次只能定位到一个位置,不能同时定位,所在放到第一个位置定位完成回调函数中再次定位
            [_geocoder geocodeAddressString:@"郑州市" completionHandler:^(NSArray *placemarks, NSError *error) {
    
                CLPlacemark *clPlacemark2 = [placemarks firstObject];
                MKPlacemark *mkPlacemark2 = [[MKPlacemark alloc] initWithPlacemark:clPlacemark2];
    
                NSDictionary *options = @{MKLaunchOptionsMapTypeKey:@(MKMapTypeStandard)};
                MKMapItem *mapItem1 = [[MKMapItem alloc] initWithPlacemark:mkPlacemark1];
                MKMapItem *mapItem2 = [[MKMapItem alloc] initWithPlacemark:mkPlacemark2];
    
                // 调用苹果地图开始导航,从 Item1 到 Item2
                [MKMapItem openMapsWithItems:@[mapItem1, mapItem2] launchOptions:options];
            }];
        }];
    • 效果

      mkmapview23mkmapview24

      mkmapview25mkmapview26

目录
相关文章
|
定位技术 iOS开发
iOS原生地图开发进阶——使用导航和附近兴趣点检索(二)
iOS原生地图开发进阶——使用导航和附近兴趣点检索
378 0
iOS原生地图开发进阶——使用导航和附近兴趣点检索(二)
|
定位技术 iOS开发
iOS原生地图开发进阶——使用导航和附近兴趣点检索(一)
iOS原生地图开发进阶——使用导航和附近兴趣点检索
292 0
|
定位技术 iOS开发
iOS原生地图开发指南再续——地图覆盖物的应用
iOS原生地图开发指南再续——地图覆盖物的应用
245 0
iOS原生地图开发指南再续——地图覆盖物的应用
|
定位技术 iOS开发 索引
iOS原生地图开发指南(二)
iOS原生地图开发指南
247 0
|
定位技术 API 开发工具
iOS原生地图开发指南(一)
iOS原生地图开发指南
467 0
iOS原生地图开发指南(一)
|
缓存 定位技术 iOS开发
iOS 定位服务与地图
介绍iOS中CoreLocation与MapKit的基本使用
1064 0