導(dǎo)航

在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)航

  1. 獲取用戶輸入的起點和終點
  2. 懶加載CLGeocoder地理編碼對象
  3. 利用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)航

  1. 獲取用戶輸入的起點和終點
  2. 懶加載CLGeocoder地理編碼對象
  3. 利用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];
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容