在iOS系統(tǒng)中,實現(xiàn)導(dǎo)航基本有以下三種方法:
- 可以將需要導(dǎo)航的位置丟給系統(tǒng)自帶的APP進(jìn)行導(dǎo)航
- 發(fā)送網(wǎng)絡(luò)請求到服務(wù)器獲取導(dǎo)航數(shù)據(jù), 自己手動繪制導(dǎo)航
- 利用三方SDK實現(xiàn)導(dǎo)航(百度)
一、系統(tǒng)自帶APP導(dǎo)航
- 獲取用戶輸入的起點和終點
- 懶加載CLGeocoder地理編碼對象
- 利用CLGeocoder對象進(jìn)行地理編碼獲取到地標(biāo)對象CLPlacemark
[self.geocoder geocodeAddressString:self.startText.text
completionHandler:^(NSArray *placemarks, NSError *error {
// 獲取開始位置的地標(biāo)
CLPlacemark *startPlace = [placemarks firstObject];
// 獲取結(jié)束位置的地標(biāo)
[self.geocoder geocodeAddressString:self.destinationText.text
completionHandler:^(NSArray *placemarks, NSError *error) {
CLPlacemark *endPlace = [placemarks firstObject];
// 開始導(dǎo)航
[self startPlacemarks:startPlace
endPlacemark:endPlace];
}];
}];
- (void)startPlacemarks:(CLPlacemark *)startPlacemark endPlacemark:(CLPlacemark *)endPlacemark {
// 創(chuàng)建起點
MKPlacemark *start = [[MKPlacemark alloc] initWithPlacemark:startPlacemark];
MKMapItem *startItem = [[MKMapItem alloc] initWithPlacemark:start];
// 創(chuàng)建終點
MKPlacemark *end = [[MKPlacemark alloc] initWithPlacemark:endPlacemark];
MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:end];
// 設(shè)置起點和終點數(shù)組
NSArray *items = @[startItem,endItem];
// 設(shè)置啟動參數(shù)
// 導(dǎo)航模式(駕車/走路)
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[MKLaunchOptionsDirectionsModeKey] = MKLaunchOptionsDirectionsModeDriving;
// 地圖顯示模式
md[MKLaunchOptionsMapTypeKey] = @(MKMapTypeHybrid);
// 只要調(diào)用MKMapItem的open方法, 就可以打開系統(tǒng)自帶的地圖APP進(jìn)行導(dǎo)航
// Items: 告訴系統(tǒng)地圖APP要從哪到哪
//launchOptions: 啟動系統(tǒng)自帶地圖APP的附加參數(shù)(導(dǎo)航的模式/是否需要先交通狀況/地圖的模式/...)
[MKMapItem openMapsWithItems:items launchOptions:dict];
}
二、手動繪制導(dǎo)航
- 獲取用戶輸入的起點和終點
- 懶加載CLGeocoder地理編碼對象
- 利用CLGeocoder對象進(jìn)行地理編碼獲取到地標(biāo)對象CLPlacemark
// 獲取開始位置的地標(biāo)
[self.geocoder geocodeAddressString:startStr
completionHandler:^(NSArray *placemarks, NSError *error) {
if (placemarks.count == 0) return;
// 開始位置的地標(biāo)
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];
//獲取結(jié)束位置的地標(biāo)
[self.geocoder geocodeAddressString:endStr
completionHandler:^(NSArray *placemarks, NSError *error) {
if (placemarks.count == 0) return;
// 結(jié)束位置的地標(biāo)
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];
// 開始導(dǎo)航
[self startDirectionsWithstartCLPlacemark:startCLPlacemark
endCLPlacemark:endCLPlacemark];
}];
}];
4.發(fā)送請求獲取路線相關(guān)信息
/**
* 發(fā)送請求獲取路線相信信息
* @param startCLPlacemark 起點的地標(biāo)
* @param endCLPlacemark 終點的地標(biāo)
*/
- (void)startDirectionsWithstartCLPlacemark:(CLPlacemark *)startCLPlacemark
endCLPlacemark:(CLPlacemark *)endCLPlacemark {
// 創(chuàng)建起點對象
MKPlacemark *startPlacemark = [[MKPlacemark alloc] initWithPlacemark:startCLPlacemark];
MKMapItem *startItem = [[MKMapItem alloc] initWithPlacemark:startPlacemark];
// 創(chuàng)建終點對象
MKPlacemark *endPlacemark = [[MKPlacemark alloc] initWithPlacemark:endCLPlacemark];
MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endPlacemark];
// 創(chuàng)建request對象
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
// 設(shè)置起點
request.source = startItem;
// 設(shè)置終點
request.destination = endItem;
// 1.發(fā)送請求到蘋果的服務(wù)器獲取導(dǎo)航路線信息
// 接收一個MKDirectionsRequest請求對象, 我們需要在該對象中說清楚:從哪里 --> 到哪里
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
// 2.計算路線信息, 計算完成之后會調(diào)用blcok
// 在block中會傳入一個響應(yīng)者對象(response), 這個響應(yīng)者對象中就存放著路線信息
[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.繪制路線(本質(zhì): 往地圖上添加遮蓋)
// 傳遞當(dāng)前路線的幾何遮蓋給地圖, 地圖就會根據(jù)遮蓋自動繪制路線
// 當(dāng)系統(tǒng)開始繪制路線時會調(diào)用代理方法詢問當(dāng)前路線的寬度/顏色等信息
[self.mapVIew addOverlay:route.polyline];
}
}];
}
注意:
MKDirectionsRequest:說清楚:從哪里 --> 到哪里
MKDirectionsResponse:從哪里 --> 到哪里的具體路線信息
5.實現(xiàn)MKMapView的代理方法
// 繪制路線時就會調(diào)用(添加遮蓋時就會調(diào)用)
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
// 創(chuàng)建一條路徑遮蓋
// 注意, 創(chuàng)建線條時候,一定要制定幾何路線
MKPolylineRenderer *line = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
line.lineWidth = 5; // 路線的寬度
line.strokeColor = [UIColor redColor]; // 路線的顏色
// 返回路線
return line;
}
注意:- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay這個代理方法已經(jīng)過時。
三、集成百度iOS導(dǎo)航SDK
百度iOS導(dǎo)航 SDK是一套基于iOS 6及以上版本設(shè)備的應(yīng)用程序接口, 您可以通過該接口實現(xiàn)專業(yè)的導(dǎo)航功能:
- 路徑規(guī)劃:通過輸入起點與終點,可以發(fā)起路徑規(guī)劃。
- 導(dǎo)航功能:成功發(fā)起路徑規(guī)劃后,即可以進(jìn)入真實GPS導(dǎo)航或模擬導(dǎo)航。真實導(dǎo)航中點擊轉(zhuǎn)向標(biāo)可以切換到文字導(dǎo)航模式,文字導(dǎo)航界面點擊HUD按鈕可以進(jìn)入HUD導(dǎo)航。
- 巡航功能:也即電子狗功能,不用輸入起點終點,一鍵即可進(jìn)行巡航模式,準(zhǔn)確發(fā)現(xiàn)前方電子眼信息。
- 傳入外部GPS功能:當(dāng)SDK運行于無法獲取GPS數(shù)據(jù)的設(shè)備時,可以利用其它GPS模塊獲取GPS信息,然后通過SDK提供的接口傳入GPS數(shù)據(jù)發(fā)起導(dǎo)航或者巡航。
下面介紹使用百度iOS導(dǎo)航的具體步驟:
1.不管是要使用百度地圖SDK還是導(dǎo)航SDK,首先必須成為百度開發(fā)者,并創(chuàng)建自己的應(yīng)用。
2.獲取API Key
為了給用戶提供更安全優(yōu)質(zhì)的服務(wù),LBS開放平臺針對iOS平臺的SDK產(chǎn)品引入Key認(rèn)證機制,用戶在使用之前需要先申請配置Key,并在程序相應(yīng)位置填寫您的Key。
Key的申請地址為:http://lbsyun.baidu.com/apiconsole/key
說明:若你需要在同一個工程中同時使用導(dǎo)航SDK和地圖SDK,可以共用同一個key。
- 訪問API控制臺頁面,若您未登錄百度賬號,將會進(jìn)入百度賬號登錄頁面
- 創(chuàng)建應(yīng)用:點擊"創(chuàng)建應(yīng)用",系統(tǒng)將為您彈出創(chuàng)建AK頁面,輸入應(yīng)用名稱,將應(yīng)用類型改為:“ iOS SDK”,并輸入安全碼(安全碼為應(yīng)用的Bundle Identifier。xcode切換到Summary標(biāo)簽查看Bundle Identifier)
- 成功創(chuàng)建Key:在輸入安全碼后,點擊“確定”完成應(yīng)用的配置工作,您將會得到一個創(chuàng)建的Key。
3.下載最新的SDK,請前往:
http://lbsyun.baidu.com/index.php?title=ios-navsdk/sdkios-nav-download
4.將SDK和Framework添加進(jìn)工程:把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設(shè)置項:在Build Settings中, “Other Linker Flags”添加“-ObjC” 標(biāo)識。
6.配置.plist文件:設(shè)置 “required background modes” , “Supported interface orientations”, “NSLocationAlwaysUsageDescription”
7.開啟引擎:在AppDelegate.m添加如下頭文件
#import "BNCoreServices.h"
在函數(shù) “application:didFinishLaunchingWithOptions:” 中啟動SDK引擎。
8.發(fā)起導(dǎo)航:發(fā)起導(dǎo)航前首先需要進(jìn)行路徑規(guī)劃,如下:
//發(fā)起導(dǎo)航
- (void)startNavi{
//節(jié)點數(shù)組
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];
//發(fā)起路徑規(guī)劃
[BNCoreServices_RoutePlan startNaviRoutePlan:BNRoutePlanMode_Recommend naviNodes:nodesArray time:nil delegete:self userInfo:nil];}
算路成功后,在回調(diào)函數(shù)中發(fā)起導(dǎo)航,如下:
//算路成功回調(diào)
-(void)routePlanDidFinished:(NSDictionary *)userInfo{ NSLog(@"算路成功");
//路徑規(guī)劃成功,開始導(dǎo)航
[BNCoreServices_UI showNaviUI: BN_NaviTypeReal delegete:self isNeedLandscape:YES];
}