一、导航
导航的三种方式:
1、使用系统APP导航

import UIKit
import MapKit
class ViewController: UIViewController {
lazy var geoCoder: CLGeocoder = {
return CLGeocoder()
}()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
/**调用系统的APP进行导航**/
//从北京到上海
geoCoder.geocodeAddressString("北京") { (pls:[CLPlacemark]?, error:Error?) in
//北京地标
let gzpl = pls?.first
self.geoCoder.geocodeAddressString("上海", completionHandler: { (place:[CLPlacemark]?, error: Error?) in
//上海地标
let shpl = place?.first
self.beginNav(start: gzpl!, end: shpl!)
})
}
}
func beginNav(start: CLPlacemark, end: CLPlacemark) {
//创建起点和终点
let startMKPL:MKPlacemark = MKPlacemark(placemark: start)
let startItem: MKMapItem = MKMapItem(placemark: startMKPL)
let endMKPL:MKPlacemark = MKPlacemark(placemark: end)
let endItem:MKMapItem = MKMapItem(placemark: endMKPL)
let items:[MKMapItem] = [startItem,endItem]
//根据起点和终点以及地图启动项,来调用系统APP进行导航
let dic = [MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,MKLaunchOptionsMapTypeKey: MKMapType.standard.rawValue,MKLaunchOptionsShowsTrafficKey:true] as [String : Any]
MKMapItem.openMaps(with: items, launchOptions: dic)
}
}
2、发送网络请求给苹果服务器获取导航路线
2.1、获取导航路线

import UIKit
import MapKit
class ViewController: UIViewController {
lazy var geoCoder: CLGeocoder = {
return CLGeocoder()
}()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
geoCoder.geocodeAddressString("广州") { (pls:[CLPlacemark]?, error:Error?) in
//广州地标
let gzpl = pls?.first
self.geoCoder.geocodeAddressString("上海") { (places:[CLPlacemark]?, error:Error?) in
//上海地标
let shpl = places?.first
self.getRouteMessage(start: gzpl!, end: shpl!)
}
}
}
func getRouteMessage(start: CLPlacemark,end:CLPlacemark) {
//1.发起请求,获取导航信息
let request:MKDirectionsRequest = MKDirectionsRequest()
//设置起点和终点
let startMKPL: MKPlacemark = MKPlacemark(placemark: start)
let startItem: MKMapItem = MKMapItem(placemark: startMKPL)
request.source = startItem
let endMKPL: MKPlacemark = MKPlacemark(placemark: end)
let endItem: MKMapItem = MKMapItem(placemark: endMKPL)
request.destination = endItem
//2.根据一个导航请求,创建一个MKDirections导航对象
let directions: MKDirections = MKDirections(request: request)
//3.计算导航数据信息
directions.calculate { (response:MKDirectionsResponse?, error:Error?) in
print("已经获取到数据")
//4.解析导航数据
//routes: [MKRoute] 路线对象
//MKRoute
//name: 路线名称
//advisoryNotices: [String]:提醒信息:前方雨雪路滑,注意安全
//distance: CLLocationDistance: 距离
//expectedTravelTime: 路线行走需要的时间
//transportType: 同行方式
//polyline: MKPolyline 路线数据模型
//steps: [MKRouteStep] 每一步怎么走
//MKRouteStep
// instructions 导航提示
//notice 警告信息
//polyline 每一小段折线数据模型
//distance 每一小段的距离
//transportType 每一小段的通行方式
if error == nil{
for route in (response?.routes)!{
print("整条线路:\(route.name),\(route.distance)")
for step in route.steps{
print("step:\(step.instructions)")
}
}
}
}
}
}
2.2、绘制导航路线
1.绘制折线路线

import UIKit
import MapKit
//理论
//路线本身也属于一个覆盖层
//如果我们在地图上操作一个覆盖层视图,就等于操作覆盖层数据模型
//添加一个覆盖层 == 添加一个覆盖层数据模型
//删除一个覆盖层 == 删除一个覆盖层数据模型
class ViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
lazy var geoCoder: CLGeocoder = {
return CLGeocoder()
}()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
geoCoder.geocodeAddressString("广州") { (pls:[CLPlacemark]?, error:Error?) in
//广州地标
let gzpl = pls?.first
self.geoCoder.geocodeAddressString("上海") { (places:[CLPlacemark]?, error:Error?) in
//上海地标
let shpl = places?.first
self.getRouteMessage(start: gzpl!, end: shpl!)
}
}
}
func getRouteMessage(start: CLPlacemark,end:CLPlacemark) {
//1.发起请求,获取导航信息
let request:MKDirectionsRequest = MKDirectionsRequest()
//设置起点和终点
let startMKPL: MKPlacemark = MKPlacemark(placemark: start)
let startItem: MKMapItem = MKMapItem(placemark: startMKPL)
request.source = startItem
let endMKPL: MKPlacemark = MKPlacemark(placemark: end)
let endItem: MKMapItem = MKMapItem(placemark: endMKPL)
request.destination = endItem
//2.根据一个导航请求,创建一个MKDirections导航对象
let directions: MKDirections = MKDirections(request: request)
//3.计算导航数据信息
directions.calculate { (response:MKDirectionsResponse?, error:Error?) in
print("已经获取到数据")
//4.解析导航数据
//routes: [MKRoute] 路线对象
//MKRoute
//name: 路线名称
//advisoryNotices: [String]:提醒信息:前方雨雪路滑,注意安全
//distance: CLLocationDistance: 距离
//expectedTravelTime: 路线行走需要的时间
//transportType: 同行方式
//polyline: MKPolyline 路线数据模型
//steps: [MKRouteStep] 每一步怎么走
//MKRouteStep
// instructions 导航提示
//notice 警告信息
//polyline 每一小段折线数据模型
//distance 每一小段的距离
//transportType 每一小段的通行方式
if error == nil{
for route in (response?.routes)!{
print("整条线路:\(route.name),\(route.distance)")
//5.添加一个覆盖层数据模型
//如果调用了这个方法,地图就会查找对应的代理方法,获取对应的覆盖层视图
self.mapView.add(route.polyline)
for step in route.steps{
print("step:\(step.instructions)")
}
}
}
}
}
}
extension ViewController: MKMapViewDelegate{
//当外界添加一个覆盖层数据模型时,就会调用这个方法查找覆盖层视图(渲染层)
//mapView 地图视图
//overlay 覆盖层数据模型
// 返回覆盖层视图(渲染图层)
//提示:我们应该根据不同的”数据模型“返回不同的”覆盖层视图“
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
//如果添加的是折线数据模型,应该返回折线渲染图层MKPolylineRenderer
// let tempOverlay: MKPolyline! = overlay as! MKOverlay
let render = MKPolylineRenderer(overlay: overlay)
render.lineWidth = 10
render.strokeColor = UIColor.red
return render
}
}
2.添加圆形覆盖层

import UIKit
import MapKit
//理论
//路线本身也属于一个覆盖层
//如果我们在地图上操作一个覆盖层视图,就等于操作覆盖层数据模型
//添加一个覆盖层 == 添加一个覆盖层数据模型
//删除一个覆盖层 == 删除一个覆盖层数据模型
class ViewController: UIViewController {
@IBOutlet weak var mapView: MKMapView!
lazy var geoCoder: CLGeocoder = {
return CLGeocoder()
}()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//添加一个圆形的覆盖层 == 添加一个圆形的覆盖层数据模型
//1.创建覆盖层数据模型
let circle: MKCircle = MKCircle(center: mapView.centerCoordinate, radius: 1000000)
//添加覆盖层数据模型(调用代理方法,查找覆盖层渲染图层来展示)
mapView.add(circle)
}
}
extension ViewController: MKMapViewDelegate{
//当外界添加一个覆盖层数据模型时,就会调用这个方法查找覆盖层视图(渲染层)
//mapView 地图视图
//overlay 覆盖层数据模型
// 返回覆盖层视图(渲染图层)
//提示:我们应该根据不同的”数据模型“返回不同的”覆盖层视图“
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
let render: MKCircleRenderer = MKCircleRenderer(overlay: overlay)
render.fillColor = UIColor.yellow
render.alpha = 0.5
return render
}
}
3、使用第三方导航
----------------------------使用百度地图----------------------------
具体使用参照百度地图SDK文档
<1>使用使用百度地图SDK
1.创建地图

代码如下:
import UIKit
class ViewController: UIViewController {
lazy var mapView: BMKMapView = {
let mapView: BMKMapView = BMKMapView(frame: self.view.bounds)
//显示比例尺
mapView.showMapScaleBar = true
//设置upsideMapView的缩放等级(4-21)
mapView.zoomLevel = 17
//底图展示的地图类型
mapView.mapType = .standard
mapView.delegate = self
return mapView
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(mapView)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
mapView.viewWillAppear()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
mapView.viewWillDisappear()
}
}
extension ViewController: BMKMapViewDelegate{
}
2.一些设置

代码如下:
import UIKit
class ViewController: UIViewController {
lazy var mapView: BMKMapView = {
let mapView: BMKMapView = BMKMapView(frame: self.view.bounds)
//1、显示比例尺
mapView.showMapScaleBar = true
//2、设置upsideMapView的缩放等级(4-21)
mapView.zoomLevel = 17
//3、底图展示的地图类型
mapView.mapType = .standard
//4、打开实时路况图层
mapView.isTrafficEnabled = true
//5、打开百度城市热力图图层(百度自有数据)
mapView.isBaiduHeatMapEnabled = true
/**6、
自定义路况颜色。注意:如果需要自定义路况颜色,必须4种路况全都设置。4个参数全部合法时,自定义颜色才有效;否则全部使用默认的。
@param smooth 路况畅通对应的颜色
@param slow 路况缓行对应的颜色
@param congestion 路况拥堵对应的颜色
@param severeCongestion 路况严重拥堵对应的颜色
@return 自定义颜色合法返回true,非法返回false
*/
//Step2. 调用路况设置API,自定义颜色,其中颜色值如有一项为nil,则自定义无效,显示默认颜色样式;需要先关闭路况开关,设置自定义颜色,再打开路况打开
mapView.isTrafficEnabled = false
mapView.setCustomTrafficColorForSmooth(UIColor.gray, slow: UIColor.purple, congestion: UIColor.yellow, severeCongestion: UIColor.red)
mapView.isTrafficEnabled = true
mapView.delegate = self
return mapView
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(mapView)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
mapView.viewWillAppear()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
mapView.viewWillDisappear()
}
}
extension ViewController: BMKMapViewDelegate{
}
2.POI检索
POI(Point of Interest),中文可以翻译为“兴趣点”。在地理信息系统中,一个POI可以是一栋房子、一个商铺、一个邮筒、一个公交站等。 百度地图SDK提供五种类型的POI检索:POI城市检索、POI周边检索、POI矩形区域检索、POI室内检索以及POI详情检索。
(1)POI城市检索
城市检索是根据关键字检索适用于在「某个行政区划,如北京市、四川省等」搜索某个名称相关的POI,例如:查找北京市的“小吃”。

(2)POI周边(圆形区域)检索
周边检索是一个圆形范围,适用于以某个位置为中心点,自定义检索半径值,搜索某个位置附近的POI。例如:查找当前位置(40.051231, 116.282051)附近1000米范围内的“小吃”。

其他POI检索参考百度SDK开发指南
import UIKit
class ViewController: UIViewController {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
//1、POI城市检索
// poiCitySearch()
//2.POI周边检索对象
poiNearbySearch()
}
///1、POI城市检索
func poiCitySearch() {
//初始化POI城市检索对象
let poiSearch:BMKPoiSearch = BMKPoiSearch()
//设置POI城市检索代理
//此处需要先遵循协议<BMKPoiSearchDelegate>
poiSearch.delegate = self
//构造POI城市检索参数
let cityOption:BMKPOICitySearchOption = BMKPOICitySearchOption()
//检索关键字,必选。举例:小吃
cityOption.keyword = "小吃";
//区域名称(市或区的名字,如北京市,海淀区),最长不超过25个字符,必选
cityOption.city = "北京市";
//检索分类,可选,与keyword字段组合进行检索,多个分类以","分隔。举例:美食,烧烤,酒店
cityOption.tags = ["美食","烧烤"];
//区域数据返回限制,可选,为YES时,仅返回city对应区域内数据
cityOption.isCityLimit = true;
//POI检索结果详细程度
//cityOption.scope = BMK_POI_SCOPE_BASIC_INFORMATION;
//检索过滤条件,scope字段为BMK_POI_SCOPE_DETAIL_INFORMATION时,filter字段才有效
//cityOption.filter = filter;
//分页页码,默认为0,0代表第一页,1代表第二页,以此类推
cityOption.pageIndex = 0;
//单次召回POI数量,默认为10条记录,最大返回20条
cityOption.pageSize = 10;
//发起POI城市检索请求
let flag: Bool = poiSearch.poiSearch(inCity: cityOption)
if flag {
print("POI城市内检索成功")
}else{
print("POI城市内检索失败")
}
}
///2.POI周边检索对象
func poiNearbySearch() {
let poiSearch:BMKPoiSearch = BMKPoiSearch()
poiSearch.delegate = self
//初始化请求参数类BMKNearbySearchOption的实例
let nearbyOption: BMKPOINearbySearchOption = BMKPOINearbySearchOption()
//检索关键字,必选
nearbyOption.keywords = ["小吃"];
//检索中心点的经纬度,必选
nearbyOption.location = CLLocationCoordinate2DMake(40.051231, 116.282051);
//检索半径,单位是米。
nearbyOption.radius = 1000;
//检索分类,可选。
nearbyOption.tags = ["美食"];
//是否严格限定召回结果在设置检索半径范围内。默认值为false。
nearbyOption.isRadiusLimit = false;
//POI检索结果详细程度
//nearbyOption.scope = BMK_POI_SCOPE_BASIC_INFORMATION;
//检索过滤条件,scope字段为BMK_POI_SCOPE_DETAIL_INFORMATION时,filter字段才有效
//nearbyOption.filter = filter;
//分页页码,默认为0,0代表第一页,1代表第二页,以此类推
nearbyOption.pageIndex = 0;
//单次召回POI数量,默认为10条记录,最大返回20条。
nearbyOption.pageSize = 10;
let flag: Bool = poiSearch.poiSearchNear(by: nearbyOption)
if flag {
print("POI周边检索成功")
}else{
print("POI周边检索失败")
}
}
}
extension ViewController: BMKPoiSearchDelegate{
/**
*返回POI搜索结果
*@param searcher 搜索对象
*@param poiResult 搜索结果列表
*@param errorCode 错误码,@see BMKSearchErrorCode
*/
func onGetPoiResult(_ searcher: BMKPoiSearch!, result poiResult: BMKPOISearchResult!, errorCode: BMKSearchErrorCode) {
if errorCode == BMK_SEARCH_NO_ERROR {
//在此处理正常结果
print("检索结果返回成功:\(poiResult.poiInfoList)")
}else if errorCode == BMK_SEARCH_AMBIGUOUS_KEYWORD{
print("检索词有歧义")
}else{
print("其他检索结果错误码相关处理")
}
}
}
网友评论