【iOS】7.4 定位服务->3.2 地图框架MapKit 功能2:路线规划(导航)
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正。
本文相关目录:
================== 所属文集:【iOS】07 设备工具 ==================
7.4 定位服务->1.0 简介
7.4 定位服务->2.1.1 定位 - 官方框架CoreLocation: 请求用户授权
7.4 定位服务->2.1.2 定位 - 官方框架CoreLocation: CLLocationManager位置管理器
7.4 定位服务->2.1.3.1 定位 - 官方框架CoreLocation 功能1:地理定位
7.4 定位服务->2.1.3.2 定位 - 官方框架CoreLocation 功能2:地理编码和反地理编码
7.4 定位服务->2.1.3.3 定位 - 官方框架CoreLocation 功能3:区域监听
7.4 定位服务->2.1.4 定位 - 官方框架CoreLocation 案例:指南针效果
7.4 定位服务->2.2 定位 - locationManager框架
7.4 定位服务->3.1 地图框架MapKit 功能1:地图展示
7.4 定位服务->3.2 地图框架MapKit 功能2:路线规划(导航)
7.4 定位服务->3.3 地图框架MapKit 功能3:3D视图
7.4 定位服务->3.4 地图框架MapKit 功能4:地图截图
7.4 定位服务->3.5 地图框架MapKit 功能5:POI检索
================== 所属文集:【iOS】07 设备工具 ==================
地图框架 - MapKit目录:

本文目录:

1.0 概念

2.0 导航的3种实现方案
2.1 方案1:使用系统APP导航

代码16:使用系统APP导航 Demo
编译环境:Xcode 8.0
模拟器版本:iOS 10
Swift版本:3.0
【OC 语言】
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
@interface ViewController ()
@property (nonatomic, strong) CLGeocoder *geoCoder;
@end
@implementation ViewController
-(CLGeocoder *)geoCoder{
if (!_geoCoder) {
_geoCoder = [[CLGeocoder alloc] init];
}
return _geoCoder;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 导航包括:起点和终点 数据由苹果处理
[self.geoCoder geocodeAddressString:@"广州" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// 1. 拿到广州地标对象
CLPlacemark *gzP = [placemarks firstObject];
[self.geoCoder geocodeAddressString:@"上海" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// 2. 拿到上海地标对象
CLPlacemark *shP = [placemarks firstObject];
// 3. 调用开始导航的方法(从广州到上海)
[self directionsWithBeginPlackmark:gzP andEndPlacemark:shP];
}];
}];
}
#pragma mark - 开始导航
// 根据两个地标,向苹果服务器请求对应的行走路线信息
- (void)directionsWithBeginPlackmark:(CLPlacemark *)startPLCL andEndPlacemark:(CLPlacemark *)endPLCL{
// 创建起点:根据 CLPlacemark 地标对象创建 MKPlacemark 地标对象
MKPlacemark *startplMK = [[MKPlacemark alloc] initWithPlacemark:startPLCL];
MKMapItem *startItem = [[MKMapItem alloc] initWithPlacemark:startplMK];
// 创建终点:根据 CLPlacemark 地标对象创建 MKPlacemark 地标对象
MKPlacemark *endplMK = [[MKPlacemark alloc] initWithPlacemark:endPLCL];
MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endplMK];
// 设置导航地图启动项参数字典
NSDictionary *launchDic = @{
// 导航模式:驾驶
MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
// 地图样式:标准样式
MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),
// 显示交通:显示
MKLaunchOptionsShowsTrafficKey : @(YES),
};
// 根据 MKMapItem 的起点和终点组成数组, 通过导航地图启动项参数字典, 调用系统的地图APP进行导航
[MKMapItem openMapsWithItems:@[startItem, endItem] launchOptions:launchDic];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
【Swift】
import UIKit
import MapKit
class ViewController: UIViewController {
// MARK: - 懒加载
lazy var geoCoder: CLGeocoder = {
return CLGeocoder()
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// MARK: - 地理编码(导航包括:起点和终点 数据由苹果处理)
geoCoder.geocodeAddressString("广州") { (pls: [CLPlacemark]?, error) -> Void in
// 1. 拿到广州地标对象
let gzPL = pls?.first
self.geoCoder.geocodeAddressString("上海") { (pls: [CLPlacemark]?, error) -> Void in
// 2. 拿到上海地标对象
let shPL = pls?.first
// 3. 调用开始导航的方法(从广州到上海)
self.beginNav(gzPL!, endPLCL: shPL!)
}
}
}
//MARK: - 开始导航
func beginNav(_ startPLCL: CLPlacemark, endPLCL: CLPlacemark) {
// 获取起点
let startplMK: MKPlacemark = MKPlacemark(placemark: startPLCL)
let startItem: MKMapItem = MKMapItem(placemark: startplMK)
// 获取终点
let endplMK: MKPlacemark = MKPlacemark(placemark: endPLCL)
let endItem: MKMapItem = MKMapItem(placemark: endplMK)
// 设置起点和终点
let mapItems: [MKMapItem] = [startItem, endItem]
// 设置导航地图启动项参数字典
let dic: [String : AnyObject] = [
// 导航模式:驾驶
MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving as AnyObject,
// 地图样式:标准样式
MKLaunchOptionsMapTypeKey: MKMapType.standard.rawValue as AnyObject,
// 显示交通:显示
MKLaunchOptionsShowsTrafficKey: true as AnyObject
]
// 根据 MKMapItem 的起点和终点组成数组, 通过导航地图启动项参数字典, 调用系统的地图APP进行导航
MKMapItem.openMaps(with: mapItems, launchOptions: dic)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
运行效果:

2.2 使用手动画线导航













步骤2的方法:

步骤4的代理方法:



代码17:使用手动画线导航 Demo
编译环境:Xcode 8.0
模拟器版本:iOS 10
Swift版本:3.0
【OC 语言】
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
@interface ViewController ()<MKMapViewDelegate>
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@property (nonatomic, strong) CLGeocoder *geoCoder;
@end
@implementation ViewController
-(CLGeocoder *)geoCoder{
if (!_geoCoder) {
_geoCoder = [[CLGeocoder alloc] init];
}
return _geoCoder;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.mapView.delegate = self;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 导航包括:起点和终点 数据由苹果处理
[self.geoCoder geocodeAddressString:@"广州" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// 1. 拿到广州地标对象
CLPlacemark *gzP = [placemarks firstObject];
// 1.2 创建圆形的覆盖层数据模型
MKCircle *circle1 = [MKCircle circleWithCenterCoordinate:gzP.location.coordinate
radius:100000];
// 1.3 添加覆盖层数据模型到地图上
[self.mapView addOverlay:circle1];
[self.geoCoder geocodeAddressString:@"上海" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
// 2. 拿到上海地标对象
CLPlacemark *shP = [placemarks firstObject];
// 2.2 创建圆形的覆盖层数据模型
MKCircle *circle2 = [MKCircle circleWithCenterCoordinate:shP.location.coordinate
radius:100000];
// 2.3 添加覆盖层数据模型到地图上
[self.mapView addOverlay:circle2];
// 3. 调用开始导航的方法(从广州到上海)
[self directionsWithBeginPlackmark:gzP andEndPlacemark:shP];
}];
}];
}
#pragma mark - 开始导航
// ① 根据两个地标,发送网络请求给苹果服务器获取导航数据,请求对应的行走路线信息
- (void)directionsWithBeginPlackmark:(CLPlacemark *)startPLCL andEndPlacemark:(CLPlacemark *)endPLCL{
// 创建请求导航路线数据信息
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
// 创建起点:根据 CLPlacemark 地标对象创建 MKPlacemark 地标对象
MKPlacemark *startplMK = [[MKPlacemark alloc] initWithPlacemark:startPLCL];
request.source = [[MKMapItem alloc] initWithPlacemark:startplMK];
// 创建终点:根据 CLPlacemark 地标对象创建 MKPlacemark 地标对象
MKPlacemark *endplMK = [[MKPlacemark alloc] initWithPlacemark:endPLCL];
request.destination = [[MKMapItem alloc] initWithPlacemark:endplMK];
// 1. 创建导航对象,根据请求,获取实际路线信息
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
// 2. 调用方法, 开始发送请求,计算路线信息
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {
// ② 解析导航数据
// block遍历所有的路线方案routes (MKRoute对象)
[response.routes enumerateObjectsUsingBlock:^(MKRoute * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%@",obj.advisoryNotices);
NSLog(@"%@,%f,%f",obj.name,obj.distance,obj.expectedTravelTime);
// 添加覆盖层数据模型,路线对应的几何线路模型(由很多点组成)
// 当我们添加一个覆盖层数据模型时, 系统绘自动查找对应的代理方法, 找到对应的覆盖层"视图"
[self.mapView addOverlay:obj.polyline]; // 添加折线
// block 遍历每一种路线的每一个步骤(MKRouteStep对象)
[obj.steps enumerateObjectsUsingBlock:^(MKRouteStep * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%@",obj.instructions);// 打印步骤说明
}];
}];
// 拓展
#pragma mark - block遍历
[response.routes enumerateObjectsUsingBlock:^(MKRoute * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"1打印对象的属性:%@,2索引:%lu",obj.name,(unsigned long)idx);
// 实现在某个遍历某个索引处停止
if (idx == 0) {
NSLog(@"block停止");
*stop = YES;
}
}];
#pragma mark - for in遍历
// 不知道遍历的对象的情况
for (id obj in response.routes) {
NSLog(@"3%@",[obj name]);
}
// 已知遍历的对象的情况
for (MKRoute * _Nonnull obj in response.routes) {
NSLog(@"3%@",obj.name);
}
}];
}
#pragma mark - MKMapViewDelegate
// ③ 添加导航路线到地图
// 当添加一个覆盖层数据模型到地图上时, 地图会调用这个方法, 查找对应的覆盖层"视图"(渲染图层)
// 参数1(mapView):地图 参数2(overlay):覆盖层"数据模型" returns: 覆盖层视图
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id <MKOverlay>)overlay{
// 折线覆盖层
if ([overlay isKindOfClass:[MKPolyline class]]) {
// 创建折线渲染对象 (不同的覆盖层数据模型, 对应不同的覆盖层视图来显示)
MKPolylineRenderer *lineRenderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
lineRenderer.lineWidth = 6; // 设置线宽
lineRenderer.strokeColor = [UIColor redColor]; // 设置线颜色
return lineRenderer;
}
// 圆形覆盖层
if ([overlay isKindOfClass:[MKCircle class]]) {
MKCircleRenderer *circleRender = [[MKCircleRenderer alloc] initWithOverlay:overlay];
circleRender.fillColor = [UIColor blackColor]; // 设置填充颜色
circleRender.alpha = 0.6; // 设置透明色
return circleRender;
}
return nil;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
【Swift 语言】
import UIKit
import MapKit
class ViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
// MARK: - 懒加载
lazy var geoCoder: CLGeocoder = {
return CLGeocoder()
}()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// MARK: - 地理编码
geoCoder.geocodeAddressString("广州") { (pls: [CLPlacemark]?, error) -> Void in
// 1. 拿到广州地标对象
let gzPL = pls?.first
// 1.2 创建圆形的覆盖层数据模型
let circle1 = MKCircle(center: (gzPL?.location?.coordinate)!, radius: 100000)
// 1.3 添加覆盖层数据模型到地图上
self.mapView.add(circle1)
self.geoCoder.geocodeAddressString("上海") { (pls: [CLPlacemark]?, error) -> Void in
// 2. 拿到上海地标对象
let shPL = pls?.first
// 2.2 创建圆形的覆盖层数据模型
let circle2 = MKCircle(center: (shPL?.location?.coordinate)!, radius: 100000)
// 2.3 添加覆盖层数据模型到地图上
self.mapView.add(circle2)
// 3. 调用获取导航线路数据信息的方法
self.getRouteMessage(gzPL!, endCLPL: shPL!)
}
}
}
// MARK: - ① 根据两个地标,发送网络请求给苹果服务器获取导航数据,请求对应的行走路线信息
func getRouteMessage(_ startCLPL: CLPlacemark, endCLPL: CLPlacemark) {
// 创建请求导航路线数据信息
let request: MKDirectionsRequest = MKDirectionsRequest()
// 创建起点:根据 CLPlacemark 地标对象创建 MKPlacemark 地标对象
let sourceMKPL: MKPlacemark = MKPlacemark(placemark: startCLPL)
request.source = MKMapItem(placemark: sourceMKPL)
// 创建终点:根据 CLPlacemark 地标对象创建 MKPlacemark 地标对象
let endMKPL: MKPlacemark = MKPlacemark(placemark: endCLPL)
request.destination = MKMapItem(placemark: endMKPL)
// 1. 创建导航对象,根据请求,获取实际路线信息
let directions: MKDirections = MKDirections(request: request)
// 2. 调用方法, 开始发送请求,计算路线信息
directions.calculate { (response:MKDirectionsResponse?, error:Error?) in
if error == nil {
print(response)
// MARK: - ② 解析导航数据
// 遍历 routes (MKRoute对象):因为有多种路线
for route in (response?.routes)! {
print(route.advisoryNotices)
print(route.name, route.distance, route.expectedTravelTime)
// 添加覆盖层数据模型,路线对应的几何线路模型(由很多点组成)
// 当我们添加一个覆盖层数据模型时, 系统绘自动查找对应的代理方法, 找到对应的覆盖层"视图"
self.mapView.add(route.polyline) // 添加折线
// 遍历每一种路线的每一个步骤(MKRouteStep对象)
for step in route.steps {
print(step.instructions) // 打印步骤说明
}
}
}
}
}
}
extension ViewController: MKMapViewDelegate {
// MARK: - ③ 添加导航路线到地图
// MARK: - 当添加一个覆盖层数据模型到地图上时, 地图会调用这个方法, 查找对应的覆盖层"视图"(渲染图层)
// 参数1(mapView):地图 参数2(overlay):覆盖层"数据模型" returns: 覆盖层视图
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
var resultRender = MKOverlayRenderer()
// 折线覆盖层
if overlay.isKind(of: MKPolyline.self) {
// 创建折线渲染对象 (不同的覆盖层数据模型, 对应不同的覆盖层视图来显示)
let render: MKPolylineRenderer = MKPolylineRenderer(overlay: overlay)
render.lineWidth = 6 // 设置线宽
render.strokeColor = UIColor.red // 设置颜色
resultRender = render
}
// 圆形覆盖层
if overlay.isKind(of: MKCircle.self) {
let circleRender: MKCircleRenderer = MKCircleRenderer(overlay: overlay)
circleRender.fillColor = UIColor.black // 设置填充颜色
circleRender.alpha = 0.5 // 设置透明色
resultRender = circleRender
}
return resultRender
}
}
运行效果:

方案3:第三方SDK(百度地图)集成实现导航
疯狂整理中。。。。。!!!!!!
本文源码 Demo 详见 Github
https://github.com/shorfng/iOS_7.0_Device-Tools
作者:蓝田(Loto)
【作品发布平台】
① 简书
② 博客园
③ Gitbook(如果觉得文章太长,请阅读此平台发布的文章)
【代码托管平台】
【如有疑问,请通过以下方式交流】
① 评论区回复
② 发送邮件至 shorfng@126.com
本文版权归作者和本网站共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,谢谢合作。
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
支付宝扫一扫 向我打赏

你也可以微信 向我打赏

【iOS】7.4 定位服务->3.2 地图框架MapKit 功能2:路线规划(导航)的更多相关文章
- 【iOS】7.4 定位服务->3.1 地图框架MapKit 功能1:地图展示
> 本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. --- > 本文相关目录: ================== 所属文集:[[ ...
- 【iOS】7.4 定位服务->3.3 地图框架MapKit 功能3:3D视图
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【iOS】7.4 定位服务->3.4 地图框架MapKit 功能4:地图截图
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 检测iOS系统的定位服务
[CLLocationManager locationServicesEnabled]检测的是整个iOS系统的位置服务开关
- 【iOS】7.4 定位服务->2.1.1 定位 - 官方框架CoreLocation: 请求用户授权
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【iOS】7.4 定位服务->2.1.2 定位 - 官方框架CoreLocation: CLLocationManager(位置管理器)
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【iOS】7.4 定位服务->2.1.3.1 定位 - 官方框架CoreLocation 功能1:地理定位
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【iOS】7.4 定位服务->2.1.3.2 定位 - 官方框架CoreLocation 功能2:地理编码和反地理编码
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
- 【iOS】7.4 定位服务->2.1.3.3 定位 - 官方框架CoreLocation 功能3:区域监听
本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正. 本文相关目录: ================== 所属文集:[iOS]07 设备工具 === ...
随机推荐
- java GUI简单记事本
代码: import java.awt.*; import java.awt.event.*; import java.io.*; class MyMenu { //定义该窗体所需的组件,方便其他函数 ...
- linux下安装Mysql 以及导入数据库
1.下载mysql的rpm包,创建一个文件夹例如software来放置下面文件 可以通过wget下载具体的地址 (1)MySQL-server-5.6.10-1.rhel5.x86_64.rpm:My ...
- JavaScript中的this关键字的用法和注意点
JavaScript中的this关键字的用法和注意点 一.this关键字的用法 this一般用于指向对象(绑定对象); 01.在普通函数调用中,其内部的this指向全局对象(window); func ...
- js设计模式--单体模式
GOF里的23种设计模式, 也是在软件开发中早就存在并反复使用的模式. 如果程序员没有明确意识到他使用过某些模式, 那么下次他也许会错过更合适的设计 (这段话来自<松本行弘的程序世界>). ...
- VMware虚拟网络连接模式详解(NAT,Bridged,Host-only)
序言 如果你使用VMware安装虚拟机,那么你必定会选择网络连接,那么vmware提供主要的3种网络连接方式,我们该如何抉择呢?他们有什么不同呢?这篇我们就做一个深入. 首先打开虚拟机设置里面的网络适 ...
- 【转】Netty系列之Netty并发编程分析
http://www.infoq.com/cn/articles/netty-concurrent-programming-analysis
- BI数据分析中KPI,KGI,CSF概念
1. 行为产生数据 先来谈一谈,自己对数据基础概念的思考.我认为首先要建立的核心观点是:行为产生数据. 翻译一下这个核心观点.意思就是,当我们在思考或描述数据相关需求的时候,必然要包含这样的语素:&q ...
- Kubernetes运维生态-Heapster分析
Heapster在Kubernetes的运维生态中如下:集群的容器的监控数据收敛汇聚层 heapster1.0版本后内部分为event和metric两个进程,可制作为两个docker镜像部署为两个独立 ...
- 使用咪咕云做C站视频直链源
首先我们先百度搜索一下“咪咕云” 点击进入-->用户注册或登录 注册时选择个人用户-->前往邮箱激活-->进入邮箱激活成功后重新登录 登录后在控制台选择“云点播” 即可进行上传视频了 ...
- Jquery弹出窗口
今天讲了Jquery的弹出窗口的组成和用法: 先把引用文件的代码写好: // 每个弹窗的标识 var x =0; var idzt = new Array(); var Window = functi ...

