在iOS系统中,实现导航基本有以下三种方法:
- 可以将需要导航的位置丢给系统自带的APP进行导航
- 发送网络请求到服务器获取导航数据, 自己手动绘制导航
- 利用三方SDK实现导航(百度)
一、系统自带APP导航
- 获取用户输入的起点和终点
- 懒加载CLGeocoder地理编码对象
- 利用CLGeocoder对象进行地理编码获取到地标对象CLPlacemark
[self.geocoder geocodeAddressString:self.startText.text
completionHandler:^(NSArray *placemarks, NSError *error {
// 获取开始位置的地标
CLPlacemark *startPlace = [placemarks firstObject];
// 获取结束位置的地标
[self.geocoder geocodeAddressString:self.destinationText.text
completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *endPlace = [placemarks firstObject];
// 开始导航
[self startPlacemarks:startPlace
endPlacemark:endPlace];
}];
}];
- (void)startPlacemarks:(CLPlacemark *)startPlacemark endPlacemark:(CLPlacemark *)endPlacemark {
// 创建起点
MKPlacemark *start = [[MKPlacemark alloc] initWithPlacemark:startPlacemark];
MKMapItem *startItem = [[MKMapItem alloc] initWithPlacemark:start];
// 创建终点
MKPlacemark *end = [[MKPlacemark alloc] initWithPlacemark:endPlacemark];
MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:end];
// 设置起点和终点数组
NSArray *items = @[startItem,endItem];
// 设置启动参数
// 导航模式(驾车/走路)
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[MKLaunchOptionsDirectionsModeKey] = MKLaunchOptionsDirectionsModeDriving;
// 地图显示模式
md[MKLaunchOptionsMapTypeKey] = @(MKMapTypeHybrid);
// 只要调用MKMapItem的open方法, 就可以打开系统自带的地图APP进行导航
// Items: 告诉系统地图APP要从哪到哪
//launchOptions: 启动系统自带地图APP的附加参数(导航的模式/是否需要先交通状况/地图的模式/...)
[MKMapItem openMapsWithItems:items launchOptions:dict];
}
二、手动绘制导航
- 获取用户输入的起点和终点
- 懒加载CLGeocoder地理编码对象
- 利用CLGeocoder对象进行地理编码获取到地标对象CLPlacemark
// 获取开始位置的地标
[self.geocoder geocodeAddressString:startStr
completionHandler:^(NSArray *placemarks, NSError *error) {
if (placemarks.count == 0) return;
// 开始位置的地标
CLPlacemark *startCLPlacemark = [placemarks firstObject];
// 添加起点的大头针
CJAnnotation *startAnno = [[CJAnnotation alloc ] init];
startAnno.title = startCLPlacemark.locality;
startAnno.subtitle = startCLPlacemark.name;
startAnno.coordinate = startCLPlacemark.location.coordinate;
[self.mapVIew addAnnotation:startAnno];
//获取结束位置的地标
[self.geocoder geocodeAddressString:endStr
completionHandler:^(NSArray *placemarks, NSError *error) {
if (placemarks.count == 0) return;
// 结束位置的地标
CLPlacemark *endCLPlacemark = [placemarks firstObject];
// 添加终点的大头针
CJAnnotation *endAnno = [[CJAnnotation alloc ] init];
endAnno.title = endCLPlacemark.locality;
endAnno.subtitle = endCLPlacemark.name;
endAnno.coordinate = endCLPlacemark.location.coordinate;
[self.mapVIew addAnnotation:endAnno];
// 开始导航
[self startDirectionsWithstartCLPlacemark:startCLPlacemark
endCLPlacemark:endCLPlacemark];
}];
}];
4.发送请求获取路线相关信息
/**
* 发送请求获取路线相信信息
* @param startCLPlacemark 起点的地标
* @param endCLPlacemark 终点的地标
*/
- (void)startDirectionsWithstartCLPlacemark:(CLPlacemark *)startCLPlacemark
endCLPlacemark:(CLPlacemark *)endCLPlacemark {
// 创建起点对象
MKPlacemark *startPlacemark = [[MKPlacemark alloc] initWithPlacemark:startCLPlacemark];
MKMapItem *startItem = [[MKMapItem alloc] initWithPlacemark:startPlacemark];
// 创建终点对象
MKPlacemark *endPlacemark = [[MKPlacemark alloc] initWithPlacemark:endCLPlacemark];
MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endPlacemark];
// 创建request对象
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
// 设置起点
request.source = startItem;
// 设置终点
request.destination = endItem;
// 1.发送请求到苹果的服务器获取导航路线信息
// 接收一个MKDirectionsRequest请求对象, 我们需要在该对象中说清楚:从哪里 --> 到哪里
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
// 2.计算路线信息, 计算完成之后会调用blcok
// 在block中会传入一个响应者对象(response), 这个响应者对象中就存放着路线信息
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
// 打印获取到的路线信息
// 2.1获取所有的路线
NSArray *routes = response.routes;
for (MKRoute *route in routes) {
NSLog(@"%f千米 %f小时", route.distance / 1000, route.expectedTravelTime/ 3600);
// 3.绘制路线(本质: 往地图上添加遮盖)
// 传递当前路线的几何遮盖给地图, 地图就会根据遮盖自动绘制路线
// 当系统开始绘制路线时会调用代理方法询问当前路线的宽度/颜色等信息
[self.mapVIew addOverlay:route.polyline];
}
}];
}
注意:
MKDirectionsRequest:说清楚:从哪里 --> 到哪里
MKDirectionsResponse:从哪里 --> 到哪里的具体路线信息
5.实现MKMapView的代理方法
// 绘制路线时就会调用(添加遮盖时就会调用)
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
// 创建一条路径遮盖
// 注意, 创建线条时候,一定要制定几何路线
MKPolylineRenderer *line = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
line.lineWidth = 5; // 路线的宽度
line.strokeColor = [UIColor redColor]; // 路线的颜色
// 返回路线
return line;
}
注意:- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay这个代理方法已经过时。
三、集成百度iOS导航SDK
百度iOS导航 SDK是一套基于iOS 6及以上版本设备的应用程序接口, 您可以通过该接口实现专业的导航功能:
- 路径规划:通过输入起点与终点,可以发起路径规划。
- 导航功能:成功发起路径规划后,即可以进入真实GPS导航或模拟导航。真实导航中点击转向标可以切换到文字导航模式,文字导航界面点击HUD按钮可以进入HUD导航。
- 巡航功能:也即电子狗功能,不用输入起点终点,一键即可进行巡航模式,准确发现前方电子眼信息。
- 传入外部GPS功能:当SDK运行于无法获取GPS数据的设备时,可以利用其它GPS模块获取GPS信息,然后通过SDK提供的接口传入GPS数据发起导航或者巡航。
下面介绍使用百度iOS导航的具体步骤:
1.不管是要使用百度地图SDK还是导航SDK,首先必须成为百度开发者,并创建自己的应用。
2.获取API Key
为了给用户提供更安全优质的服务,LBS开放平台针对iOS平台的SDK产品引入Key认证机制,用户在使用之前需要先申请配置Key,并在程序相应位置填写您的Key。
Key的申请地址为:http://lbsyun.baidu.com/apiconsole/key
说明:若你需要在同一个工程中同时使用导航SDK和地图SDK,可以共用同一个key。
- 访问API控制台页面,若您未登录百度账号,将会进入百度账号登录页面
- 创建应用:点击"创建应用",系统将为您弹出创建AK页面,输入应用名称,将应用类型改为:“ iOS SDK”,并输入安全码(安全码为应用的Bundle Identifier。xcode切换到Summary标签查看Bundle Identifier)
- 成功创建Key:在输入安全码后,点击“确定”完成应用的配置工作,您将会得到一个创建的Key。
3.下载最新的SDK,请前往:
http://lbsyun.baidu.com/index.php?title=ios-navsdk/sdkios-nav-download
4.将SDK和Framework添加进工程:把baiduNaviSDK文件夹添加到工程中,把AudioToolbox.framework、ImageIO.framework、CoreMotion.framework、CoreLocation.framework、CoreTelephony.framework、MediaPlayer.framework、AVFoundation.framework、SystemConfiguration.framework、libstdc++6.0.9.dylib、Security.framework、JavaScriptCore.framework,这几个framework添加到工程中。
5.修改Build Settings设置项:在Build Settings中, “Other Linker Flags”添加“-ObjC” 标识。
6.配置.plist文件:设置 “required background modes” , “Supported interface orientations”, “NSLocationAlwaysUsageDescription”
7.开启引擎:在AppDelegate.m添加如下头文件
#import "BNCoreServices.h"
在函数 “application:didFinishLaunchingWithOptions:” 中启动SDK引擎。
8.发起导航:发起导航前首先需要进行路径规划,如下:
//发起导航
- (void)startNavi{
//节点数组
NSMutableArray *nodesArray = [[NSMutableArray alloc] initWithCapacity:2];
//起点
BNRoutePlanNode *startNode = [[BNRoutePlanNode alloc] init];
startNode.pos = [[BNPosition alloc] init]; startNode.pos.x = 113.936392;
startNode.pos.y = 22.547058;
startNode.pos.eType = BNCoordinate_BaiduMapSDK; [nodesArray addObject:startNode];
//终点
BNRoutePlanNode *endNode = [[BNRoutePlanNode alloc] init];
endNode.pos = [[BNPosition alloc] init];
endNode.pos.x = 114.077075;
endNode.pos.y = 22.543634;
endNode.pos.eType = BNCoordinate_BaiduMapSDK; [nodesArray addObject:endNode];
//发起路径规划
[BNCoreServices_RoutePlan startNaviRoutePlan:BNRoutePlanMode_Recommend naviNodes:nodesArray time:nil delegete:self userInfo:nil];}
算路成功后,在回调函数中发起导航,如下:
//算路成功回调
-(void)routePlanDidFinished:(NSDictionary *)userInfo{ NSLog(@"算路成功");
//路径规划成功,开始导航
[BNCoreServices_UI showNaviUI: BN_NaviTypeReal delegete:self isNeedLandscape:YES];
}