一、细说百度地图的路径规划
路径规划主要有这么几种
1.公交路径规划
1.1 市内公交规划(暂时不在这里说)
1.2 跨市/省公交规划
// 导入头文件
#import <BaiduMapAPI_Search/BMKSearchComponent.h>
#import <BaiduMapAPI_Map/BMKPolylineView.h>
#import <BaiduMapAPI_Utils/BMKGeometry.h>
#pragma mark: - 公交路线
- (void)showBusSearch {
//线路检索节点信息
BMKPlanNode *start = [[BMKPlanNode alloc] init];
start.pt = self.userLocation.location.coordinate;
start.cityName = @"南宁";
BMKPlanNode *end = [[BMKPlanNode alloc] init];
// 108.296699,22.842406
CLLocationCoordinate2D endCoordinate = CLLocationCoordinate2DMake(22.842406, 108.296699);
end.pt = endCoordinate;
end.cityName = @"南宁";
BMKMassTransitRoutePlanOption *drivingRouteSearchOption = [[BMKMassTransitRoutePlanOption alloc] init];
drivingRouteSearchOption.from = start;
drivingRouteSearchOption.to = end;
BOOL flag = [_routesearch massTransitSearch:drivingRouteSearchOption];
if (flag) {
NSLog(@"%s - 设置成功!",__func__);
}else {
debugLog(@"设置失败");
}
}
/**
*返回公共交通路线检索结果(new)回调方法
*@param searcher 搜索对象
*@param result 搜索结果,类型为BMKMassTransitRouteResult
*@param error 错误号,@see BMKSearchErrorCode
*/
- (void)onGetMassTransitRouteResult:(BMKRouteSearch*)searcher result:(BMKMassTransitRouteResult*)result errorCode:(BMKSearchErrorCode)error {
debugLog(@"公交方案-%@",result.routes);
if (error == BMK_SEARCH_NO_ERROR) {
for (int i = 0; i < result.routes.count; i++ ) {
BMKMassTransitRouteLine *massTransitRouteLine = result.routes[i];
// 保存换乘说明
NSMutableArray *instructions = [NSMutableArray array];
// 换乘的交通工具
NSMutableArray *stepTypes = [NSMutableArray array];
// 价格信息
debugLog(@"价格-%f",massTransitRouteLine.price);
debugLog(@"时间分钟-%d",massTransitRouteLine.duration.minutes);
debugLog(@"起点-%@",massTransitRouteLine.starting.title);
debugLog(@"终点-%@",massTransitRouteLine.terminal.title);
debugLog(@"路段方案%@",massTransitRouteLine.steps);
// 所有路段的信息
for ( int j = 0; j < massTransitRouteLine.steps.count; j++) {
BMKMassTransitStep *step = massTransitRouteLine.steps[j];
debugLog(@"%@",step.steps);
for ( int k = 0; k< step.steps.count; k++) {
BMKMassTransitSubStep *subStep = step.steps[k];
debugLog(@"换乘说明-%@",subStep.instructions);
[instructions addObject:subStep.instructions];
debugLog(@"路段类型-%u",subStep.stepType);
if(subStep.stepType != 5) { // 5为步行
if (subStep.vehicleInfo.name) {
[stepTypes addObject:subStep.vehicleInfo.name];
}
}
// 当路段为公交路段或地铁路段时,可以获取交通工具信息
debugLog(@"交通工具信息-%@",subStep.vehicleInfo.name);
}
}
}
}
}
2.驾车路径规划
#pragma mark 驾车路线
-(void)showDriveSearch {
//线路检索节点信息
BMKPlanNode *start = [[BMKPlanNode alloc] init];
start.pt = self.userLocation.location.coordinate;
start.cityName = @"南宁";
BMKPlanNode *end = [[BMKPlanNode alloc] init];
CLLocationCoordinate2D endCoordinate = CLLocationCoordinate2DMake(22.842406, 108.296699);
end.pt = endCoordinate;
end.cityName = @"南宁";
BMKDrivingRoutePlanOption *drivingRouteSearchOption = [[BMKDrivingRoutePlanOption alloc] init];
drivingRouteSearchOption.from = start;
drivingRouteSearchOption.to = end;
BOOL flag = [_routesearch drivingSearch:drivingRouteSearchOption];
if (flag) {
NSLog(@"%s - 设置成功!",__func__);
}else {
debugLog(@"设置失败");
}
}
#pragma mark 返回驾乘搜索结果
- (void)onGetDrivingRouteResult:(BMKRouteSearch*)searcher result:(BMKDrivingRouteResult*)result errorCode:(BMKSearchErrorCode)error {
if (error == BMK_SEARCH_NO_ERROR) {
for (int i = 0; i < result.routes.count; i++) {
NSMutableArray *instruction = [NSMutableArray array];
NSMutableArray *waypoints = [NSMutableArray array];
//表示一条驾车路线
BMKDrivingRouteLine *plan = result.routes[i];
for (int k = 0; k < plan.wayPoints.count; k++) {
BMKPlanNode *node = plan.wayPoints[k];
[waypoints addObject:node.name];
}
for (int j = 0; j < plan.steps.count; j++) {
//表示驾车路线中的一个路段
BMKDrivingStep* transitStep = [plan.steps objectAtIndex:j];
[instruction addObject:transitStep.instruction];
}
}
}
}
3.步行路径规划
#pragma mark: - 步行
- (void)showWalkSearch {
//线路检索节点信息
BMKPlanNode *start = [[BMKPlanNode alloc] init];
start.pt = self.userLocation.location.coordinate;
start.cityName = @"南宁";
BMKPlanNode *end = [[BMKPlanNode alloc] init];
CLLocationCoordinate2D endCoordinate = CLLocationCoordinate2DMake(22.842406, 108.296699);
end.pt = endCoordinate;
end.cityName = @"南宁";
BMKWalkingRoutePlanOption *drivingRouteSearchOption = [[BMKWalkingRoutePlanOption alloc] init];
drivingRouteSearchOption.from = start;
drivingRouteSearchOption.to = end;
BOOL flag = [_routesearch walkingSearch:drivingRouteSearchOption];
if (flag) {
NSLog(@"%s - 设置成功!",__func__);
}else {
debugLog(@"设置失败");
}
}
/**
*返回步行搜索结果
*@param searcher 搜索对象
*@param result 搜索结果,类型为BMKWalkingRouteResult
*@param error 错误号,@see BMKSearchErrorCode
*/
- (void)onGetWalkingRouteResult:(BMKRouteSearch*)searcher result:(BMKWalkingRouteResult*)result errorCode:(BMKSearchErrorCode)error {
debugLog(@"步行方案--%@",result.routes);
if (error == BMK_SEARCH_NO_ERROR) {
for (int i = 0; i < result.routes.count; i++) {
NSMutableArray *instructions = [NSMutableArray array];
BMKWalkingRouteLine *walkingRouteLine = result.routes[i];
//debugLog(@"途径 ---%@", walkingRouteLine.wayPointPoiList);
debugLog(@"路线长度 -- %d", walkingRouteLine.distance);
debugLog(@"需要花费的时间 %d",walkingRouteLine.duration.minutes);
for (int j = 0; j < walkingRouteLine.steps.count; j++) {
BMKWalkingStep *step = walkingRouteLine.steps[j];
debugLog(@"入口信息 -- %@",step.entraceInstruction);
debugLog(@"出口信息 -- %@",step.exitInstruction);
debugLog(@"指示信息 -- %@",step.instruction);
[instructions addObject:step.instruction];
}
}
}
}
4.骑车路径规划(暂时不总结)
5.根据路径规划划线
- (void)showCarRoutePlan {
// 计算路线方案中的路段数目
int size = (int)[self.drivingRouteLine.steps count];
BMKDrivingRouteLine *plan = self.drivingRouteLine;
int planPointCounts = 0;
for (int i = 0; i < size; i++) {
//表示驾车路线中的一个路段
BMKDrivingStep* transitStep = [plan.steps objectAtIndex:i];
if(i==0){
RouteAnnotation* item = [[RouteAnnotation alloc]init];
item.coordinate = plan.starting.location;
item.title = @"起点";
item.type = 0;
[_mapView addAnnotation:item]; // 添加起点标注
}else if(i==size-1){
RouteAnnotation* item = [[RouteAnnotation alloc]init];
item.coordinate = plan.terminal.location;
item.title = @"终点";
item.type = 1;
[_mapView addAnnotation:item]; // 添加终点标注
}
//添加annotation节点
RouteAnnotation* item = [[RouteAnnotation alloc]init];
item.coordinate = transitStep.entrace.location;
item.title = transitStep.entraceInstruction;
item.degree = transitStep.direction * 30;
item.type = 4;
[_mapView addAnnotation:item];
//轨迹点总数累计
planPointCounts += transitStep.pointsCount;
}
// 添加途经点
if (plan.wayPoints) {
for (BMKPlanNode* tempNode in plan.wayPoints) {
RouteAnnotation* item = [[RouteAnnotation alloc]init];
item.coordinate = tempNode.pt;
item.type = 5;
item.title = tempNode.name;
[_mapView addAnnotation:item];
}
}
//轨迹点
BMKMapPoint * temppoints = new BMKMapPoint[planPointCounts];
int i = 0;
for (int j = 0; j < size; j++) {
BMKDrivingStep* transitStep = [plan.steps objectAtIndex:j];
int k=0;
for(k=0;k<transitStep.pointsCount;k++) {
temppoints[i].x = transitStep.points[k].x;
temppoints[i].y = transitStep.points[k].y;
i++;
}
}
// 通过points构建BMKPolyline
BMKPolyline* polyLine = [BMKPolyline polylineWithPoints:temppoints count:planPointCounts];
[_mapView addOverlay:polyLine]; // 添加路线overlay
delete []temppoints;
[self mapViewFitPolyLine:polyLine];
}
- (void)showBusRoutePlan {
BMKMassTransitRouteLine *routeLine = self.massTransitRouteLine;
BOOL startCoorIsNull = YES;
CLLocationCoordinate2D startCoor;//起点经纬度
CLLocationCoordinate2D endCoor;//终点经纬度
NSInteger size = [routeLine.steps count];
NSInteger planPointCounts = 0;
for (NSInteger i = 0; i < size; i++) {
BMKMassTransitStep *transitStep = [routeLine.steps objectAtIndex:i];
for (BMKMassTransitSubStep *subStep in transitStep.steps) {
//添加annotation节点
RouteAnnotation *item = [[RouteAnnotation alloc]init];
item.coordinate = subStep.entraceCoor;
item.title = subStep.instructions;
item.type = 2;
[_mapView addAnnotation:item];
if (startCoorIsNull) {
startCoor = subStep.entraceCoor;
startCoorIsNull = NO;
}
endCoor = subStep.exitCoor;
//轨迹点总数累计
planPointCounts += subStep.pointsCount;
//steps中是方案还是子路段,YES:steps是BMKMassTransitStep的子路段(A到B需要经过多个steps);NO:steps是多个方案(A到B有多个方案选择)
if (transitStep.isSubStep == NO) {//是子方案,只取第一条方案
break;
}
else {
//是子路段,需要完整遍历transitStep.steps
}
}
}
//添加起点标注
RouteAnnotation *startAnnotation = [[RouteAnnotation alloc]init];
startAnnotation.coordinate = startCoor;
startAnnotation.title = @"起点";
startAnnotation.type = 0;
[_mapView addAnnotation:startAnnotation]; // 添加起点标注
//添加终点标注
RouteAnnotation *endAnnotation = [[RouteAnnotation alloc]init];
endAnnotation.coordinate = endCoor;
endAnnotation.title = @"终点";
endAnnotation.type = 1;
[_mapView addAnnotation:endAnnotation]; // 添加起点标注
//轨迹点
BMKMapPoint *temppoints = new BMKMapPoint[planPointCounts];
NSInteger index = 0;
for (BMKMassTransitStep *transitStep in routeLine.steps) {
for (BMKMassTransitSubStep *subStep in transitStep.steps) {
for (NSInteger i = 0; i < subStep.pointsCount; i++) {
temppoints[index].x = subStep.points[i].x;
temppoints[index].y = subStep.points[i].y;
index++;
}
//steps中是方案还是子路段,YES:steps是BMKMassTransitStep的子路段(A到B需要经过多个steps);NO:steps是多个方案(A到B有多个方案选择)
if (transitStep.isSubStep == NO) {//是子方案,只取第一条方案
break;
}
else {
//是子路段,需要完整遍历transitStep.steps
}
}
}
// 通过points构建BMKPolyline
BMKPolyline *polyLine = [BMKPolyline polylineWithPoints:temppoints count:planPointCounts];
[_mapView addOverlay:polyLine]; // 添加路线overlay
delete []temppoints;
[self mapViewFitPolyLine:polyLine];
}
- (void)showWalkRoutePlan {
BMKWalkingRouteLine *plan = self.walkingRouteLine;
NSInteger size = [plan.steps count];
int planPointCounts = 0;
for (int i = 0; i < size; i++) {
BMKWalkingStep *transitStep = [plan.steps objectAtIndex:i];
if(i==0){
RouteAnnotation *item = [[RouteAnnotation alloc]init];
item.coordinate = plan.starting.location;
item.title = @"起点";
item.type = 0;
[_mapView addAnnotation:item]; // 添加起点标注
}else if(i==size-1){
RouteAnnotation *item = [[RouteAnnotation alloc]init];
item.coordinate = plan.terminal.location;
item.title = @"终点";
item.type = 1;
[_mapView addAnnotation:item]; // 添加起点标注
}
//添加annotation节点
RouteAnnotation *item = [[RouteAnnotation alloc]init];
item.coordinate = transitStep.entrace.location;
item.title = transitStep.entraceInstruction;
item.degree = transitStep.direction *30;
item.type = 4;
[_mapView addAnnotation:item];
//轨迹点总数累计
planPointCounts += transitStep.pointsCount;
}
//轨迹点
BMKMapPoint *temppoints = new BMKMapPoint[planPointCounts];
int i = 0;
for (int j = 0; j < size; j++) {
BMKWalkingStep *transitStep = [plan.steps objectAtIndex:j];
int k=0;
for(k=0;k<transitStep.pointsCount;k++) {
temppoints[i].x = transitStep.points[k].x;
temppoints[i].y = transitStep.points[k].y;
i++;
}
}
// 通过points构建BMKPolyline
BMKPolyline *polyLine = [BMKPolyline polylineWithPoints:temppoints count:planPointCounts];
[_mapView addOverlay:polyLine]; // 添加路线overlay
delete []temppoints;
[self mapViewFitPolyLine:polyLine];
}
#pragma mark - 显示大头针
- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>)annotation {
if (![annotation isKindOfClass:[RouteAnnotation class]]) return nil;
return [self getRouteAnnotationView:mapView viewForAnnotation:(RouteAnnotation *)annotation];
}
#pragma mark 获取路线的标注,显示到地图
- (BMKAnnotationView*)getRouteAnnotationView:(BMKMapView *)mapview viewForAnnotation:(RouteAnnotation*)routeAnnotation {
BMKAnnotationView *view = nil;
switch (routeAnnotation.type) {
case 0:
{
view = [mapview dequeueReusableAnnotationViewWithIdentifier:@"start_node"];
if (view == nil) {
view = [[BMKAnnotationView alloc] initWithAnnotation:routeAnnotation reuseIdentifier:@"start_node"];
view.image = [UIImage imageNamed:@"map_start"];
//[UIImage imageWithContentsOfFile:[self getMyBundlePath1:@"images/icon_nav_start"]];
view.centerOffset = CGPointMake(0, -(view.frame.size.height * 0.5));
view.canShowCallout = true;
}
view.annotation = routeAnnotation;
}
break;
case 1:
{
view = [mapview dequeueReusableAnnotationViewWithIdentifier:@"end_node"];
if (view == nil) {
view = [[BMKAnnotationView alloc] initWithAnnotation:routeAnnotation reuseIdentifier:@"end_node"];
view.image = [UIImage imageNamed:@"map_end"];
//[UIImage imageWithContentsOfFile:[self getMyBundlePath1:@"images/icon_nav_end"]];
view.centerOffset = CGPointMake(0, -(view.frame.size.height * 0.5));
view.canShowCallout = true;
}
view.annotation =routeAnnotation;
}
break;
case 4:
{
view = [mapview dequeueReusableAnnotationViewWithIdentifier:@"route_node"];
if (view == nil) {
view = [[BMKAnnotationView alloc] initWithAnnotation:routeAnnotation reuseIdentifier:@"route_node"];
view.canShowCallout = true;
} else {
[view setNeedsDisplay];
}
UIImage *image = [UIImage imageWithContentsOfFile:[self getMyBundlePath1:@"images/icon_direction"]];
view.image = [image imageRotatedByDegrees:routeAnnotation.degree];
view.annotation = routeAnnotation;
}
break;
default:
break;
}
return view;
}
#pragma mark 根据overlay生成对应的View
-(BMKOverlayView *)mapView:(BMKMapView *)mapView viewForOverlay:(id<BMKOverlay>)overlay {
if ([overlay isKindOfClass:[BMKPolyline class]]) {
BMKPolylineView* polylineView = [[BMKPolylineView alloc] initWithOverlay:overlay];
polylineView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:1];
polylineView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
polylineView.lineWidth = 3.0;
return polylineView;
}
return nil;
}
#pragma mark 根据polyline设置地图范围
- (void)mapViewFitPolyLine:(BMKPolyline *) polyLine {
CGFloat ltX, ltY, rbX, rbY;
if (polyLine.pointCount < 1) return;
BMKMapPoint pt = polyLine.points[0];
ltX = pt.x, ltY = pt.y;
rbX = pt.x, rbY = pt.y;
for (int i = 0; i < polyLine.pointCount; i++) {
BMKMapPoint pt = polyLine.points[i];
if (pt.x < ltX) {
ltX = pt.x;
}
if (pt.x > rbX) {
rbX = pt.x;
}
if (pt.y > ltY) {
ltY = pt.y;
}
if (pt.y < rbY) {
rbY = pt.y;
}
}
BMKMapRect rect;
rect.origin = BMKMapPointMake(ltX , ltY);
rect.size = BMKMapSizeMake(rbX - ltX, rbY - ltY);
[_mapView setVisibleMapRect:rect];
_mapView.zoomLevel = _mapView.zoomLevel - 0.3;
}
// RouteAnnotation 自定义的类
/** 路线的标注*/
@interface RouteAnnotation : BMKPointAnnotation
@property (nonatomic) int type; ///<0:起点 1:终点 2:公交 3:地铁 4:驾乘 5:途经点
@property (nonatomic) int degree;
@end
@implementation RouteAnnotation
@end
二、使用本机的地图导航
通常自己的手机都会安装有百度地图、高德地图、腾讯等等
1.实现步骤
1.1 添加应用白名单
<string>baidumap</string>
<string>iosamap</string>
<string>comgooglemaps</string>
<string>qqmap</string>
1.2 info.plist
添加对应的url schemes
百度地图: baidumap://
腾讯地图: qqmap://
谷歌地图: comgooglemaps://
高德地图: iosamap://
1.3 使用的第三方框架
pod 'LCActionSheet' // 弹窗选择
pod 'JZLocationConverter' // 经纬度转换(主要解决百度地图和谷歌地图用的不是同一种标准的问题)
1.4 具体实现代码
// 引入头文件
#import <LCActionSheet/LCActionSheet.h>
#import <JZLocationConverter/JZLocationConverter.h>
#pragma mark - 导航方法
- (NSArray *)getInstalledMapApp
{
NSArray *locationArray = [self.poiMD.address_x_y componentsSeparatedByString:@","];
// lat lng
CLLocationCoordinate2D endLocation = CLLocationCoordinate2DMake([locationArray.lastObject floatValue], [locationArray.firstObject floatValue]);
NSMutableArray *maps = [NSMutableArray array];
//苹果地图
NSMutableDictionary *iosMapDic = [NSMutableDictionary dictionary];
iosMapDic[@"title"] = @"苹果地图";
[maps addObject:iosMapDic];
//百度地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"baidumap://"]]) {
NSMutableDictionary *baiduMapDic = [NSMutableDictionary dictionary];
baiduMapDic[@"title"] = @"百度地图";
NSString *urlString = [[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=latlng:%f,%f|name=北京&mode=driving&coord_type=gcj02",endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
baiduMapDic[@"url"] = urlString;
[maps addObject:baiduMapDic];
}
//高德地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"iosamap://"]]) {
NSMutableDictionary *gaodeMapDic = [NSMutableDictionary dictionary];
gaodeMapDic[@"title"] = @"高德地图";
NSString *urlString = [[NSString stringWithFormat:@"iosamap://navi?sourceApplication=%@&backScheme=%@&lat=%f&lon=%f&dev=0&style=2",@"导航功能",@"nav123456",endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
gaodeMapDic[@"url"] = urlString;
[maps addObject:gaodeMapDic];
}
//谷歌地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) {
NSMutableDictionary *googleMapDic = [NSMutableDictionary dictionary];
googleMapDic[@"title"] = @"谷歌地图";
NSString *urlString = [[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%f,%f&directionsmode=driving",@"导航测试",@"nav123456",endLocation.latitude, endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
googleMapDic[@"url"] = urlString;
[maps addObject:googleMapDic];
}
//腾讯地图
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"qqmap://"]]) {
NSMutableDictionary *qqMapDic = [NSMutableDictionary dictionary];
qqMapDic[@"title"] = @"腾讯地图";
NSString *urlString = [[NSString stringWithFormat:@"qqmap://map/routeplan?from=我的位置&type=drive&tocoord=%f,%f&to=终点&coord_type=1&policy=0",endLocation.latitude, endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
qqMapDic[@"url"] = urlString;
[maps addObject:qqMapDic];
}
return maps;
}
- (void)showLCActionSheet {
NSArray *maps = [self getInstalledMapApp];
NSMutableArray *mapsA = [NSMutableArray array];
for (NSDictionary *dict in maps) {
[mapsA addObject:dict[@"title"]];
}
LCActionSheet *actionSheet = [LCActionSheet sheetWithTitle:@"请选择" cancelButtonTitle:@"取消" clicked:^(LCActionSheet * _Nonnull actionSheet, NSUInteger buttonIndex) {
debugLog(@"当前选择 --- %d",buttonIndex);
if (buttonIndex == 0) { // 当前选择了取消
return ;
}
if ((buttonIndex - 1) == 0) { // 苹果地图无论如何都是有的
[self navAppleMap];
return;
}
NSDictionary *dic = [self getInstalledMapApp][buttonIndex - 1];
NSString *urlString = dic[@"url"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
} otherButtonTitleArray:mapsA];
actionSheet.blurEffectStyle = UIBlurEffectStyleLight;
actionSheet.scrolling = YES;
actionSheet.visibleButtonCount = 3.6f;
[actionSheet show];
}
// 苹果地图
- (void)navAppleMap
{
NSArray *locationArray = [self.poiMD.address_x_y componentsSeparatedByString:@","];
// lat lng
CLLocationCoordinate2D endLocation = CLLocationCoordinate2DMake([locationArray.lastObject floatValue], [locationArray.firstObject floatValue]);
CLLocationCoordinate2D gps = [JZLocationConverter bd09ToWgs84:endLocation];
MKMapItem *currentLoc = [MKMapItem mapItemForCurrentLocation];
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:gps addressDictionary:nil]];
NSArray *items = @[currentLoc,toLocation];
NSDictionary *dic = @{
MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),
MKLaunchOptionsShowsTrafficKey : @(YES)
};
[MKMapItem openMapsWithItems:items launchOptions:dic];
}