iOS百度地圖路徑規(guī)劃和POI檢索詳細(xì)總結(jié)

開篇

喵神鎮(zhèn)樓.jpg

最近寫簡(jiǎn)書不多,除了前段時(shí)間一篇匆匆的FFMPEG的理論學(xué)習(xí)基本沒(méi)寫多少,主要是最近比較忙,又是硬件設(shè)備的調(diào)試,又是新需求的加入,今天就來(lái)寫一下項(xiàng)目中的一個(gè)知識(shí),閑話少敘直入正題吧。

iPhone_6_-_iPhone_6___iOS_9_3__13E230_.png

百度地圖的使用

百度地圖API的導(dǎo)入網(wǎng)上說(shuō)了許多坑,不過(guò)我遇到的比較少,這里就放兩個(gè)比較常見(jiàn)的吧。
坑一:


奧聯(lián)WIFI_xcodeproj.png

如上圖所示,在infoplist里加入這個(gè)字段,而且這里還可以設(shè)置提示的內(nèi)容。不加的話,嘿嘿嘿,期待你的嘗試。
坑二:如下圖


Pasted_Graphic_jpg.png

導(dǎo)入百度地圖API運(yùn)行之后報(bào)上圖錯(cuò)誤大約18到20個(gè)左右,解決方法添加libstdc++.6.0.9 的庫(kù)。
填完坑之后看一下我們今天要演示的效果吧。
路線規(guī)劃圖.gif

這里實(shí)現(xiàn)的內(nèi)容就是在定位到的當(dāng)前城市內(nèi)的路徑規(guī)劃,實(shí)現(xiàn)駕車,公交,步行三種規(guī)劃方式。

注意要點(diǎn):
  • 這里我們采用的是地點(diǎn)到地點(diǎn)之間的路徑規(guī)劃,所以我們?cè)诓樵兊倪^(guò)程中一定要設(shè)置查詢的城市,不然無(wú)法查找成功(當(dāng)然也可以用經(jīng)緯度的方式,那就另說(shuō)了)。

  • 方式切換問(wèn)題,如果我們想要像上圖所示的不同路徑規(guī)劃間的切換,我們要注意的就是地圖上已經(jīng)存在的路線軌跡和標(biāo)注的清除問(wèn)題。

  • 我們?cè)诓煌瑮l件下規(guī)劃路徑要注意他們是不同的查詢方法,以及他們不同的協(xié)議方法,這個(gè)我們可以具體點(diǎn)進(jìn)百度地圖靜態(tài)庫(kù)的方法去查看。

代碼的實(shí)現(xiàn)

由于在項(xiàng)目中,并沒(méi)有整理出來(lái),這里我們就貼一些主要的代碼。
因?yàn)槿N路徑規(guī)劃其實(shí)原理一致這里我們以駕車的路徑規(guī)劃做一個(gè)例子。
因?yàn)橐櫦暗皆诖酥笆欠裼熊壽E和標(biāo)注因此我們要先做清除處理,代碼如下


    [_mapView removeOverlays:_mapView.overlays];

    NSArray *annArray = [[NSArray alloc]initWithArray:_mapView.annotations];

    [_mapView removeAnnotations: annArray];

之后我們創(chuàng)建路徑規(guī)劃的方法

  _searcher = [[BMKRouteSearch alloc]init];
  _searcher.delegate = self;

 //發(fā)起檢索
    BMKPlanNode* start = [[BMKPlanNode alloc]init] ;
    start.name = _startFiled.text;

    BMKPlanNode* end = [[BMKPlanNode alloc]init];

    end.name =  _endFiled.text;

    start.cityName = self.city;

    end.cityName = self.city;

    BMKDrivingRoutePlanOption *driveRouteSearchOption =[[BMKDrivingRoutePlanOption alloc]init];

    driveRouteSearchOption.from = start;

    driveRouteSearchOption.to = end;


這里要注意的就是因?yàn)槲覀兪邱{車路徑規(guī)劃,所以創(chuàng)建的是BMKDrivingRoutePlanOption,我們進(jìn)入到內(nèi)部方法可以看到,入過(guò)我們是公交和步行對(duì)應(yīng)的則是他們各自的Option,發(fā)起檢索成功后會(huì)調(diào)取他的協(xié)議方法,這里的前提是要遵循BMKRouteSearchDelegate協(xié)議

- (void)onGetDrivingRouteResult:(BMKRouteSearch*)searcher result:(BMKDrivingRouteResult*)result errorCode:(BMKSearchErrorCode)error

在上述的協(xié)議方法中,我們?cè)O(shè)置起點(diǎn),終點(diǎn),以及路段入口信息和各軌跡點(diǎn)的總數(shù)

 for (int i = 0; i < size; i++) {
            BMKDrivingStep *tansitStep = [plan.steps objectAtIndex:i];
            if (i == 0 ) {

                BMKPointAnnotation* annotation = [[BMKPointAnnotation alloc]init];

                annotation.coordinate = plan.terminal.location;
                annotation.title = @"起點(diǎn)";
                [_mapView addAnnotation:annotation];

            } else if (i == size - 1) {

                BMKPointAnnotation* annotation = [[BMKPointAnnotation alloc]init];

                annotation.coordinate = plan.terminal.location;
                annotation.title = @"終點(diǎn)";
                [_mapView addAnnotation:annotation];


            }

            BMKPointAnnotation* annotation = [[BMKPointAnnotation alloc]init];

            annotation.coordinate =  tansitStep.entrace.location; //路段入口信息

            annotation.title = tansitStep.instruction; //路程換成說(shuō)明
            [_mapView addAnnotation:annotation];

            //軌跡點(diǎn)總數(shù)累計(jì)
            planPointCounts += tansitStep.pointsCount;
        }

        //軌跡點(diǎn)
        BMKMapPoint * temppoints = new BMKMapPoint[planPointCounts]; //文件后綴名改為mm
        int i = 0;
        for (int j = 0; j < size; j++) {
            BMKTransitStep *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++;
            }
        }
        //通過(guò)points構(gòu)建BMKPolyline
        BMKPolyline *polyLine = [BMKPolyline polylineWithPoints:temppoints count:planPointCounts];
        [_mapView addOverlay:polyLine]; //添加路線overlay
        delete []temppoints;
        [self mapViewFitPolyLine:polyLine];

這樣我們就完成了路徑規(guī)劃的主要設(shè)置。

POI檢索

百度地圖提供了詳細(xì)的POI檢索,如下圖我們?cè)O(shè)置一個(gè)界面選擇我們想要檢索的內(nèi)容,然后根據(jù)我們選擇的內(nèi)容去在地圖上標(biāo)記處各個(gè)對(duì)應(yīng)的點(diǎn),并顯示出他的詳細(xì)信息。然后我們點(diǎn)擊具體的cell,然后我們根據(jù)模型中的數(shù)據(jù)地點(diǎn)或者經(jīng)緯度,可以規(guī)劃處我們所在地到目的地的線路規(guī)劃,一樣有駕車,公交,步行,三種。這里不得不吐槽一下為啥那么多電話都沒(méi)有嘞。


IMG_0003.PNG
IMG_0004.PNG

我們要進(jìn)行POI檢索,首先要遵循BMKPoiSearchDelegate協(xié)議,然后進(jìn)行檢索

  _searcher2 =[[BMKPoiSearch alloc]init];

    _searcher2.delegate = self;
    //發(fā)起檢索
    BMKNearbySearchOption *option = [[BMKNearbySearchOption alloc]init];
    option.pageIndex = 1;  //當(dāng)前索引頁(yè)
    option.pageCapacity = 10; //分頁(yè)量

    option.location = CLLocationCoordinate2DMake(self.lat2, self.lon2);

    option.keyword = self.str;

    option.radius = 3000;


    BOOL flag = [_searcher2 poiSearchNearBy:option];

    if(flag)
    {
        NSLog(@"周邊檢索發(fā)送成功");
    }
    else
    {
        NSLog(@"周邊檢索發(fā)送失敗");
    }

檢索成功后會(huì)走到協(xié)議方法

- (void)onGetPoiResult:(BMKPoiSearch*)searcher result:(BMKPoiResult*)poiResultList errorCode:(BMKSearchErrorCode)error

在這里我們得到了包含詳細(xì)信息的一個(gè)數(shù)組,然后我們?nèi)〕鯞MKPoiInfo對(duì)象中的uid,去進(jìn)行詳細(xì)檢索,同時(shí)并把它轉(zhuǎn)換為一個(gè)model,去創(chuàng)建我們的tableview,然后把得到的對(duì)應(yīng)數(shù)據(jù)展示到下半部的列表中,在點(diǎn)擊tableview的詳細(xì)事件中進(jìn)行傳值,實(shí)現(xiàn)路線的規(guī)劃。model中的部分屬性如下:

@interface GSMapModel : NSObject
///POI名稱
@property (nonatomic, strong) NSString* name;
///POIuid
@property (nonatomic, strong) NSString* uid;
///POI地址
@property (nonatomic, strong) NSString* address;
///POI所在城市
@property (nonatomic, strong) NSString* city;
///POI電話號(hào)碼
@property (nonatomic, strong) NSString* phone;
///POI郵編
@property (nonatomic, strong) NSString* postcode;

詳情檢索對(duì)應(yīng)的協(xié)議方法

//搜索的詳細(xì)結(jié)果
- (void)onGetPoiDetailResult:(BMKPoiSearch*)searcher result:(BMKPoiDetailResult*)poiDetailResult errorCode:(BMKSearchErrorCode)errorCode{

    if (errorCode == BMK_SEARCH_NO_ERROR) {
        //在此處理正常結(jié)果

    }
    else if (errorCode == BMK_SEARCH_AMBIGUOUS_KEYWORD){
        //當(dāng)在設(shè)置城市未找到結(jié)果,但在其他城市找到結(jié)果時(shí),回調(diào)建議檢索城市列表
        // result.cityList;
        NSLog(@"起始點(diǎn)有歧義");
    } else {
        NSLog(@"抱歉,未找到結(jié)果");
    }

大頭針的自定義

我們想要自己定義我們想要看到的大頭針模樣,就要對(duì)他進(jìn)行自定義。下面介紹一種簡(jiǎn)單的處理大頭針樣式的方法,如果想要具體的根據(jù)不同的情形來(lái)進(jìn)行自定義,就要進(jìn)行判斷,根據(jù)他們不同的情況去給定相應(yīng)的標(biāo)注圖片

- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id<BMKAnnotation>)annotation{

    BMKPinAnnotationView *newAnnotationView = [[BMKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"myAnnotation"];

    newAnnotationView.pinColor = BMKPinAnnotationColorPurple;

    newAnnotationView.animatesDrop = NO;// 設(shè)置該標(biāo)注點(diǎn)動(dòng)畫顯示

    newAnnotationView.annotation=annotation;

    newAnnotationView.image = [UIImage imageNamed:@"mapicon"];   //把大頭針換成別的圖片

    newAnnotationView.size = CGSizeMake(20, 33);

    return newAnnotationView;
}

后記

地圖中我們用的比較多的就是定位,POI檢索和路徑規(guī)劃了,定位的話,相信不管是官方SDK還是網(wǎng)上各種資料都?jí)蛟敿?xì)的了,我就不再重復(fù)了,這里主要對(duì)路徑規(guī)劃和POI檢索做出說(shuō)明,希望對(duì)大家有所幫助。

補(bǔ)充內(nèi)容

今天有小伙伴問(wèn)看了文章想知道百度地圖的模糊搜索是怎么做的,輸入地名就能自動(dòng)聯(lián)想好厲害的樣子,這里就補(bǔ)充一下吧,其實(shí)也是POI搜索的一部分,是城市內(nèi)搜索根據(jù)輸入的地名發(fā)起搜索,然后把搜索內(nèi)容展示到tableview上罷了。如下圖:

模糊搜索.gif

當(dāng)我們改變輸入框的內(nèi)容時(shí)其實(shí)內(nèi)部的操作是什么呢,下面我們一點(diǎn)點(diǎn)介紹一下他。
這里我們要做的是POI檢索,因此首先要遵循BMKPoiSearchDelegate協(xié)議,創(chuàng)建搜索的代碼如下:

  _poisearcher = [[BMKPoiSearch alloc]init];

    _poisearcher.delegate = self;

    BMKCitySearchOption *citySearchOption = [[BMKCitySearchOption alloc]init];

    citySearchOption.pageIndex = 0;

    citySearchOption.pageCapacity = 20;

     citySearchOption.city= self.city;

    citySearchOption.keyword = _inputFiled.text;

成功之后會(huì)走下面這個(gè)協(xié)議方法

-(void)onGetPoiResult:(BMKPoiSearch *)searcher result:(BMKPoiResult *)poiResult errorCode:(BMKSearchErrorCode)errorCode

這里我們就得到了返回的內(nèi)容,然后把它里面的數(shù)據(jù)取到轉(zhuǎn)換為模型展示到tableview上就好了,但是,為什么是但是呢,因?yàn)槟氵@樣做并不能得到想要的結(jié)果,因?yàn)槟氵@里做的檢索只是一次的,并不能實(shí)現(xiàn)每改變一個(gè)字就重新檢索展示出地點(diǎn),我們要對(duì)輸入框做處理

  [_inputFiled addTarget:self action:@selector(inputaction:) forControlEvents:UIControlEventEditingChanged];

添加事件,實(shí)現(xiàn)對(duì)輸入框變化的監(jiān)聽,然后實(shí)現(xiàn)方法。

#pragma mark - 輸入框的實(shí)時(shí)監(jiān)聽
-(void)inputaction:(UITextField *)textField{
    [self performSelector:@selector(delay) withObject:self afterDelay:0.5];
}

這里我們監(jiān)聽輸入框的變化,然后把相應(yīng)的檢索寫到delay方法中就可以了。這樣就實(shí)現(xiàn)了數(shù)據(jù)的展示,然后點(diǎn)擊對(duì)應(yīng)的cell的時(shí)候,把數(shù)據(jù)傳給上個(gè)界面接Ok了啊,這里為了用戶體驗(yàn)我們可以監(jiān)聽tableview的滾動(dòng),當(dāng)滾動(dòng)的時(shí)候讓輸入框的鍵盤消失,代碼如下:

#pragma mark -滾動(dòng)隱藏鍵盤
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{

    [self.view endEditing:YES];
}

這樣我們就實(shí)現(xiàn)了模糊搜索了,是不是還是比較簡(jiǎn)單的。有別的問(wèn)題以后再接著補(bǔ)充吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容