iOS

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);
    	}
    
  • 效果

    mkmapview1 mkmapview2

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];
      
    • 效果

      mkmapview3 mkmapview4

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;
    	    }
    	}
    
  • 效果

    mkmapview5 mkmapview6

    mkmapview7 mkmapview8

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;
    
    • 效果

      mkmapview9 mkmapview10

  • 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;
    
    • 效果

      mkmapview11 mkmapview12

  • 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;
      	}
      
    • 效果

      mkmapview13 mkmapview14

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;
    	}
    
  • 效果

    mkmapview15 mkmapview16

    mkmapview17 mkmapview18

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];
    	    }
    	}
    
  • 效果

    mkmapview19 mkmapview27

    mkmapview28 mkmapview20

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];
    	}];
    
    • 效果

      mkmapview21 mkmapview22

  • 从位置 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];
            }];
        }];
    
    • 效果

      mkmapview23 mkmapview24

      mkmapview25 mkmapview26

原文地址:https://www.cnblogs.com/QianChia/p/6250980.html