iOS核心笔记—MapKit框架-导航

1、导航简介:

?了解:导航,简单来说,就是根据用户指定的位置,进行路线规划;然后根据用户在行走过程中,实时的给出指引提示。


1-1、iOS导航实现方案:
方案 详细说明
方案一 将需要导航的位置传递给系统的地图APP进行导航
方案二 发送网络请求到Apple服务器/公司服务器获取导航数据,然后,手动绘制导航路线
方案三 利用第三方SDK实现导航功能(百度地图)

?说明:通常如果需要手动绘制导航路线,都是向Apple服务器发送请求、获取导航信息;此处,只对方案一、方案二做详细介绍,方案三将单独说明。


2、系统自带地图APP导航:

?了解采用逆推法,实现使用Apple系统自带地图进行导航;该方式导航关键在于:[MKMapItem openMapsWithItems:导航路线点 launchOptions:启动参数]


2-1、详细步骤:
步骤 详细介绍 备注
第一步 设置导航路线的起点、终点,将目标地址地理编码成CLLPlacemark地标对象,根据CLLPlacemark对象创建MKPlacemark对象,MKPlacemark对象在地图上代表每一个点、再根据MKPlacemark对象创建对应的模型,即:MKMapItem对象 MKMapItem
第二步 设置起点、终点模型数组,配置打开系统地图APP启动参数 启动地图应用前相关准备工作
第三步 通过MKMapItem的openMapsWithItems:launchOptions:方法打开系统自带地图进行导航 MKMapItem类方法

?重要:通过地理编码获取目标位置的CLPlacemark对象,再根据CLPlacemark对象创建MKPlacemark对象;然后,根据MKPlacemark对象创建对应的数据模型对象MKMapItem对象,最后,将所有的导航路线的数据模型对象包装成数组,通过MKMapItem对象的openMapsWithItems:launchOptions:类方法传递给系统自带地图APP;最终,系统自带地图APP根据传入的数据模型对象完成导航操作。


2-2、补充说明:
  • 1、打开系统地图应用时,如果没有设置启动参数,用户进入系统地图之后需要一步一步自主获取导航信息。
  • 2、MKPlacemark继承自CLPlacemark,所以,通过CLPlacemark对象可以创建一个MKPlacemark对象。
  • 3、通过MKMapItem的mapItemForCurrentLocation类方法可以直接获取当前用户所在位置对应的数据模型,但是,需要请求用户定位授权,因为,牵涉到定位用户当前所在位置。
  • 4、使用自带地图APP进行导航的本质:是确定导航路线中要经过的点(CLLPlacemark - - -> MKPlacemark),再将地图上导航所需要用到的地标对象(MKPlacemark)转换成对应的模型(MKMapItem),再将所有的模型通过MKMapItem的openMapsWithItems:launchOptions:类方法传递给系统地图APP,这样就能借助系统地图对指定位置进行导航。
  • 5、使用系统地图APP进行导航核心类:MKMapItem、MKPlacemark。

2-3、示例代码:
1.    // MARK: - 设置起点、终点2.    // 1. 将当前位置设置为起点模型3.    MKMapItem *beginItem = [MKMapItem mapItemForCurrentLocation];4.5.    // 2. 设置终点6.    [self.geocoder geocodeAddressString:@"长沙" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {7.        // 2.1 获取地标对象8.        CLPlacemark *clPlacemark = [placemarks firstObject];9.10.        // 2.2 根据CLPlacemark创建MKPlacemark11.        MKPlacemark *endPlacemark = [[MKPlacemark alloc] initWithPlacemark:clPlacemark];12.13.        // 2.3 创建终点模型14.        MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endPlacemark];15.16.        // MARK: - 使用MKMapItem打开系统地图进行导航17.        // 1. 起点、终点模型数组18.        NSArray *items = @[beginItem, endItem];19.20.        // 2. 设置启动参数21.        NSDictionary *dict = @{22.                MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,23.                MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),24.                MKLaunchOptionsShowsTrafficKey : @(YES)25.                               };26.27.        // 3. 打开系统地图APP, 进行导航28.        [MKMapItem openMapsWithItems:items launchOptions:dict];29.    }];

3、手动绘制导航路线:

?了解:想要实现手动绘制导航路线,需要向Apple服务器发送网络请求获取导航路线;需要记住关键对象:导航对象 - - -> MKDirections

?重要:显示在屏幕上的导航路线也是一个覆盖层,在地图上操作覆盖层,其实操作的是覆盖层的数据模型;删除覆盖层:在地图上移除覆盖层数据模型;添加覆盖层:在地图上添加覆盖层数据模型。


3-1、详细步骤:
步骤 详细介绍 备注
第一步 创建导航请求对象(MKDirectionsRequest),在该对象中保存有本次导航的起点模型(MKMapItem)、终点模型(MKMapItem),MKDirectionsRequest对象的source、destination属性专门用来保存起点、终点模型 创建请求
第二步 通过导航请求对象创建导航对象(MKDirections) 创建导航对象
第三步 导航对象(MKDirections)调用calculateDirectionsWithCompletionHandler:方法开始向Apple服务器发送请求、获取导航数据信息 获取导航数据
第四步 从Apple服务器获取到导航数据之后开始解析数据(注:导航数据存放在响应体MKDirectionsResponse对象中),从response中便能获取导航路线对象数组、遍历该数组获取导航路线对象(MKRoute)、将导航路线对象中的要显示的渲染图层对应的数据模型添加到mapView中 解析导航数据
第五步 实现返回要显示在mapView上的渲染图层代理方法,在该代理方法中创建渲染图层(MKPolylineRenderer、MKCircleRenderer,具体渲染图层由添加到mapView中的数据模型的类型决定;MKPolyline:折线数据模型,MKCircle:原型数据模型) 返回渲染图层

3-2、详细说明示例图:

?说明:本质:向Apple服务器发送请求,获取导航数据;获取的导航数据实质是导航路线对象,将导航路线对象中的渲染图层数据模型属性添加到mapView;实现mapView的代理方法,在代理方法中创建渲染图层、并设置相关属性,系统自动将渲染图层添加到mapView上面。


3-3、示例代码:
1.#import "ViewController.h"2.#import <MapKit/MapKit.h>3.[email protected] ViewController () <MKMapViewDelegate>5./** 地图 */[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;7./** 地理编码 */[email protected] (strong, nonatomic) CLGeocoder *geocoder;9./** 位置管理者对象 */[email protected] (strong, nonatomic) CLLocationManager *mgr;11.[email protected]13.[email protected] ViewController15.16.- (void)viewDidLoad {17.    [super viewDidLoad];18.19.    // MARK: - 请求授权20.    self.mgr = [CLLocationManager new];21.    if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {22.        [self.mgr requestWhenInUseAuthorization];23.    }24.25.    // MARK: - 设置代理26.    self.mapView.delegate = self;27.}28.29.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{30.    // MARK: - 开始导航31.    [self.geocoder geocodeAddressString:@"长沙" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {32.        // 0. 地理编码失败, 返回33.        if (placemarks.count == 0 || error) {34.            NSLog(@"地理编码失败");35.            return ;36.        }37.38.        // MARK: - 创建导航请求对象39.        MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];40.41.        // MARK: - 设置起点、终点模型42.        // 1. 起点模型, 使用该方式获取当前点对应的数据模型 "需要请求用户定位授权"43.        MKMapItem *beginItem = [MKMapItem mapItemForCurrentLocation];44.        request.source = beginItem;45.46.        // 2. 设置终点47.        CLPlacemark *endCL = placemarks.firstObject;48.        MKPlacemark *endPL = [[MKPlacemark alloc] initWithPlacemark:endCL];49.        MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endPL];50.        request.destination = endItem;51.52.        // 3. 根据MKDirectionsRequest对象, 创建导航对象53.        MKDirections *direction = [[MKDirections alloc] initWithRequest:request];54.55.        // 4. 计算导航路线56.        [direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {57.58.            if (error != nil) {59.                NSLog(@"导航失败");60.            }61.            NSLog(@"%zd", response.routes.count);62.63.            // 4.1. 遍历导航路线对象数组, MKRoute : 导航路线对象64.            [response.routes enumerateObjectsUsingBlock:^(MKRoute * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {65.                // 4.2 将导航路线对象中保存的渲染图层对应的数据模型添加到mapView中66.                [self.mapView addOverlay:obj.polyline];67.            }];68.        }];69.    }];70.}71.72.#pragma mark - <MKMapViewDelegate>73.- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{74.    // 1. 创建折线渲染图层75.    MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];76.77.    // 2. 设置折线渲染图层相关属性78.    renderer.lineWidth = 10;  // 折线渲染图层折线线宽79.    renderer.strokeColor = [UIColor greenColor];  // 折线渲染图层折线颜色80.81.    // 3. 返回折线渲染图层82.    return renderer;83.}84.85.#pragma mark - 懒加载86.- (CLGeocoder *)geocoder{87.    if (_geocoder == nil) {88.        _geocoder = [[CLGeocoder alloc] init];89.    }90.    return _geocoder;91.}[email protected]

4、重要类:

4-1、MKDirectionsResponse—响应体对象:
属性名 作用
source 导航起点位置模型
destination 导航终点位置模型
routes 导航路线对象数组,数组中存放MKRoute对象

4-2、MKRoute—导航路线对象:
属性名 作用
name 导航路线名称
advisoryNotices 导航路线中注意、警告信息
distance 导航路线长度(实际物理距离,单位:m)
polyline 导航路线渲染图层几何形状数据模型(即:该数据模型对应的渲染图层的形状为折线,将来往mapView中添加该类型数据模型时,在代理方法中应当创建折线渲染图层返回)
steps 多个行走步骤组成的数组(例如“前方路口左转”,“保持直行”等等, MKRouteStep 对象)

?注意:MKRoute是一整条路,MKRouteStep是这条长路中的每一节。


4-3、MKRouteStep—导航步骤对象:
属性名 作用
instructions 步骤说明(例如“前方路口左转”,“保持直行”等)
transportType 交通方式(驾车,步行等)
polyline 路线对应的在地图上的几何线路数据模型(由很多点组成,可绘制在地图上)

5、导航渲染图层效果:

5-1、折线渲染图层效果:

示例代码:

1.#import "ViewController.h"2.#import <MapKit/MapKit.h>3.[email protected] ViewController () <MKMapViewDelegate>5./** 地图 */[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;7./** 地理编码 */[email protected] (strong, nonatomic) CLGeocoder *geocoder;9./** 位置管理者对象 */[email protected] (strong, nonatomic) CLLocationManager *mgr;[email protected]12.[email protected] ViewController14.15.- (void)viewDidLoad {16.    [super viewDidLoad];17.18.    // MARK: - 设置代理19.    self.mapView.delegate = self;20.21.    // MARK: - 请求授权22.    self.mgr = [[CLLocationManager alloc] init];23.    if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {24.        [self.mgr requestWhenInUseAuthorization];25.    }26.}27.28.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{29.    // MARK: - 创建导航请求对象30.    MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];31.32.    // 1. 设置起点数据模型33.    MKMapItem *beginItem = [MKMapItem mapItemForCurrentLocation];34.35.    // 2. 设置终点数据模型36.    [self.geocoder geocodeAddressString:@"耒阳" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {37.        // 3. 创建MKPlacemark对象38.        CLPlacemark *endCL = placemarks.firstObject;39.        MKPlacemark *endPL = [[MKPlacemark alloc] initWithPlacemark:endCL];40.41.        // 4. 创建终点数据模型42.        MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endPL];43.44.        // 5. 设置为请求对象45.        request.source = beginItem;46.        request.destination = endItem;47.48.        // MARK: - 创建导航对象49.        MKDirections *direcion = [[MKDirections alloc] initWithRequest:request];50.51.        // 1. 计算导航数据52.        [direcion calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {53.            // 2. 防错处理54.            if (placemarks.count == 0 || error) {55.                NSLog(@"请求导航错误");56.                return ;57.            }58.59.            // 3. 遍历导航路线对象数组, 将折线渲染图层数据模型添加到mapView60.            [response.routes enumerateObjectsUsingBlock:^(MKRoute * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {61.                // 4. 将渲染层数据模型添加mapView62.                [self.mapView addOverlay:obj.polyline];63.            }];64.        }];65.    }];66.}67.68.#pragma mark - <MKMapViewDelegate>69.- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{70.    // 1. 创建折线渲染图层71.    MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];72.73.    // 2. 设置相关属性74.    renderer.lineWidth = 10;75.    renderer.strokeColor = [UIColor redColor];76.77.    // 3. 返回折线渲染图层78.    return renderer;79.}80.81.#pragma mark - 地理编码82.- (CLGeocoder *)geocoder{83.    if (_geocoder == nil) {84.        _geocoder = [[CLGeocoder alloc] init];85.    }86.    return _geocoder;87.}[email protected]


效果示例图


5-2、圆形渲染图层效果:

示例代码

1.#import "ViewController.h"2.#import <MapKit/MapKit.h>3.[email protected] ViewController () <MKMapViewDelegate>5./** 地图 */[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;7.[email protected]9.[email protected] ViewController11.12.- (void)viewDidLoad {13.    [super viewDidLoad];14.15.    // MARK: - 设置mapView的代理16.    self.mapView.delegate = self;17.}18.19.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{20.    // MARK: - 添加圆形渲染图层模型21.    // 1. 圆形渲染图层中心点22.    CLLocationCoordinate2D center = CLLocationCoordinate2DMake(40, 116);23.24.    // 2. 创建圆形渲染图层数据模型25.    MKCircle *circle = [MKCircle circleWithCenterCoordinate:center radius:1000000];26.27.    // 3. 添加到mapView28.    [self.mapView addOverlay:circle];29.}30.31.#pragma mark - <MKMapViewDelegate>32./**33. 当往mapView中添加数据模型时, 便会调用该方法返回对应的渲染图层34.35. @param mapView 地图36. @param overlay 渲染图层模型37. @return 渲染图层38. */39.- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{40.    // 1. 创建圆形渲染图层41.    MKCircleRenderer *renderer = [[MKCircleRenderer alloc] initWithOverlay:overlay];42.43.    // 2. 设置属性44.    renderer.fillColor = [UIColor greenColor];45.    renderer.alpha = 0.5;46.47.    // 3. 返回圆形渲染图层48.    return renderer;49.}[email protected]


效果示例图


时间: 2024-10-13 12:07:22

iOS核心笔记—MapKit框架-导航的相关文章

iOS核心笔记—MapKit框架-基础

1.MapKit框架简介: ?了解:MapKit框架使用须知:①.MapKit框架中所有的数据类型的前缀都是MK:②.需要导入#import <MapKit/MapKit.h>头文件:③.MapKit框架中有一个非常重要的UI控件:MKMapView,专门用于地图显示,例如:大头针.路线.覆盖层展示等(着重界面展示). 1-1.地图设置: 1-1-1.设置地图显示类型: 地图类型: 地图枚举 地图类型 MKMapTypeStandard 普通地图 MKMapTypeSatellite 卫星云图

iOS核心笔记—CoreLocation框架-基础

1.CoreLocation框架简介: ?了解:在iOS开发中,要想使用地图和定位功能,必须基于2个框架进行开发.CoreLocation框架:主要用于地理定位:MapKit框架:主要用于地图展示. 1-1.CoreLocation框架功能: 功能 作用 地理定位 定位用户所在位置,获取对应的经纬度.海拔等位置信息 区域监听 事先在APP内部通过代码指定一个区域,当用户进入.或离开该区域的时候,可以通过对应的代理方法监听到用户的位置 地理编码 将详细的位置信息转换为对应的经纬度,即:位置信息 -

iOS核心笔记——UICollectionView-布局对象

iOS核心笔记--UICollectionView-布局对象 1.UICollectionView布局对象: 1-1.UICollectionViewLayout: ?了解:1.UICollectionViewLayout没有itemSize属性,而collectionView的cell的大小不能为0或者小于0:所以,通常collectionView使用其子类UICollectionViewFlowLayout布局cell. ?了解:2.UICollectionViewLayout中声明了布局可

iOS核心笔记——UICollectionView-辅助视图

iOS核心笔记--UICollectionView-辅助视图 1.UICollectionView辅助视图: ?了解:UICollectionView中的头部视图.尾部视图都是使用注册机制 + 重用机制,提高程序的执行效率,其头尾部视图类型均为:UICollectionReusableView.注册辅助视图时使用字符串区分注册的视图为头部还是尾部视图,其区分字符串为:UICollectionElementKindSectionHeader(头部视图).UICollectionElementKin

iOS学习笔记—— MapKit

在iOS应用程序中,我们可以使用Map Kit API开发地图应用,其核心是MKMapView类.本次主要实现的功能是显示地图,添加标注,跟踪用户位置变化. (本日志的所有内容基于已成功获取坐标位置,获取方法见上篇日志) 1.显示地图 首先需要引用<MapKit/MapKit.h>,它的委托协议是 MKMapViewDelegate. 初始化MapView mapView = [[MKMapView alloc] initWithFrame:CGRectMake(5, 120, self.vi

iOS核心笔记——多线程-GCD

1.GCD简介: ?了解:GCD全称为"Grand Central Dispatch",纯C语言,GCD提供了非常多功能强大的函数:GCD中所有的函数都包含于Libdispatch库中. 1-1.使用GCD的优势: ?了解:1.GCD是苹果公司为多核的并行运算提出的解决方案: ?了解:2.GCD会自动利用更多的CPU内核(例如:双核.四核): ?了解:3.GCD会自动管理线程的生命周期(创建线程.调度任务.销毁线程). 1-2.GCD两大核心概念: 名称 作用: 任务 执行什么操作 队

iOS核心笔记——网络编程-网络安全

1.数据安全: 1.01 攻城利器:Charles(公司中一般都使用该工具来抓包,并做网络测试)2.注意:Charles在使用中的乱码问题,可以显示包内容,然后打开info.plist文件,找到java目录下面的VMOptions,在后面添加一项:-Dfile.encoding=UTF-83.02 数据安全的原则4. 1)在网络上"不允许"传输用户隐私数据的"明文"5. 2.)在本地"不允许"保存用户隐私数据的"明文"6.03

iOS核心笔记——RunLoop-基础

1.RunLoop介绍: ?了解:RunLoop从字面意思看就是运行循环.跑圈,通常情况下,一个线程一次只能执行一个任务:任务执行完毕后线程就会进入消亡状态随之退出.有时候我们希望线程执行完任务之后还能随时处理事件且不退出,所以,iOS提供了RunLoop. 1-1.什么是RunLoop? ?重要:RunLoop实际上就是一个对象,RunLoop对象管理其需要处理的事件和消息:RunLoop能够让线程在没有处理消息时进入休眠状态以避免占用资源.在监听到事件源发送的消息时立刻唤醒线程.RunLoo

iOS核心笔记——CALayer-基本使用

1.CALayer简单使用: ※了解: 通过操作CALayer对象,可以很方便的调整UIView的一些界面属性,例如:阴影.圆角大小.边框宽度--等:在iOS 7.0以前使用CALayer需要手动导入QuartzCore框架. 2.通过CALayer修改UIView的界面属性: 1.在storyboard中拖入UIView,并设置相关属性: 如下图所示: 2.设置阴影: 1. // 1. 设置阴影颜色2. self.blueView.layer.shadowColor = [UIColor bl