開篇
喵神鎮樓.jpg
最近寫簡書不多,除了前段時間一篇匆匆的FFMPEG的理論學習基本沒寫多少,主要是最近比較忙,又是硬件設備的調試,又是新需求的加入,今天就來寫一下項目中的一個知識,閒話少敘直入正題吧。
路徑規劃.png
百度地圖的使用
百度地圖API的導入網上說了許多坑,不過我遇到的比較少,這裡就放兩個比較常見的吧。
坑一:
奧聯WIFI_xcodeproj.png
如上圖所示,在infoplist裡加入這個字段,而且這裡還可以設置提示的內容。不加的話,嘿嘿嘿,期待你的嘗試。
坑二:如下圖
Pasted_Graphic_jpg.png
導入百度地圖API運行之後報上圖錯誤大約18到20個左右,解決方法添加libstdc++.6.0.9 的庫。
填完坑之後看一下我們今天要演示的效果吧。
路線規劃圖.gif
這裡實現的內容就是在定位到的當前城市內的路徑規劃,實現駕車,公交,步行三種規劃方式。
注意要點:
這裡我們采用的是地點到地點之間的路徑規劃,所以我們在查詢的過程中一定要設置查詢的城市,不然無法查找成功(當然也可以用經緯度的方式,那就另說了)。
方式切換問題,如果我們想要像上圖所示的不同路徑規劃間的切換,我們要注意的就是地圖上已經存在的路線軌跡和標注的清除問題。
我們在不同條件下規劃路徑要注意他們是不同的查詢方法,以及他們不同的協議方法,這個我們可以具體點進百度地圖靜態庫的方法去查看。
代碼的實現
由於在項目中,並沒有整理出來,這裡我們就貼一些主要的代碼。
因為三種路徑規劃其實原理一致這裡我們以駕車的路徑規劃做一個例子。
因為要顧及到在此之前是否有軌跡和標注因此我們要先做清除處理,代碼如下
[_mapView removeOverlays:_mapView.overlays]; NSArray *annArray = [[NSArray alloc]initWithArray:_mapView.annotations]; [_mapView removeAnnotations: annArray];
之後我們創建路徑規劃的方法
_searcher = [[BMKRouteSearch alloc]init]; _searcher.delegate = self; //發起檢索 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;
這裡要注意的就是因為我們是駕車路徑規劃,所以創建的是BMKDrivingRoutePlanOption,我們進入到內部方法可以看到,入過我們是公交和步行對應的則是他們各自的Option,發起檢索成功後會調取他的協議方法,這裡的前提是要遵循BMKRouteSearchDelegate協議
- (void)onGetDrivingRouteResult:(BMKRouteSearch*)searcher result:(BMKDrivingRouteResult*)result errorCode:(BMKSearchErrorCode)error
在上述的協議方法中,我們設置起點,終點,以及路段入口信息和各軌跡點的總數
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 = @"起點"; [_mapView addAnnotation:annotation]; } else if (i == size - 1) { BMKPointAnnotation* annotation = [[BMKPointAnnotation alloc]init]; annotation.coordinate = plan.terminal.location; annotation.title = @"終點"; [_mapView addAnnotation:annotation]; } BMKPointAnnotation* annotation = [[BMKPointAnnotation alloc]init]; annotation.coordinate = tansitStep.entrace.location; //路段入口信息 annotation.title = tansitStep.instruction; //路程換成說明 [_mapView addAnnotation:annotation]; //軌跡點總數累計 planPointCounts += tansitStep.pointsCount; } //軌跡點 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++; } } //通過points構建BMKPolyline BMKPolyline *polyLine = [BMKPolyline polylineWithPoints:temppoints count:planPointCounts]; [_mapView addOverlay:polyLine]; //添加路線overlay delete []temppoints; [self mapViewFitPolyLine:polyLine];
這樣我們就完成了路徑規劃的主要設置。
POI檢索
百度地圖提供了詳細的POI檢索,如下圖我們設置一個界面選擇我們想要檢索的內容,然後根據我們選擇的內容去在地圖上標記處各個對應的點,並顯示出他的詳細信息。然後我們點擊具體的cell,然後我們根據模型中的數據地點或者經緯度,可以規劃處我們所在地到目的地的線路規劃,一樣有駕車,公交,步行,三種。這裡不得不吐槽一下為啥那麼多電話都沒有嘞。
我們要進行POI檢索,首先要遵循BMKPoiSearchDelegate協議,然後進行檢索
_searcher2 =[[BMKPoiSearch alloc]init]; _searcher2.delegate = self; //發起檢索 BMKNearbySearchOption *option = [[BMKNearbySearchOption alloc]init]; option.pageIndex = 1; //當前索引頁 option.pageCapacity = 10; //分頁量 option.location = CLLocationCoordinate2DMake(self.lat2, self.lon2); option.keyword = self.str; option.radius = 3000; BOOL flag = [_searcher2 poiSearchNearBy:option]; if(flag) { NSLog(@"周邊檢索發送成功"); } else { NSLog(@"周邊檢索發送失敗"); }
檢索成功後會走到協議方法
- (void)onGetPoiResult:(BMKPoiSearch*)searcher result:(BMKPoiResult*)poiResultList errorCode:(BMKSearchErrorCode)error
在這裡我們得到了包含詳細信息的一個數組,然後我們取出BMKPoiInfo對象中的uid,去進行詳細檢索,同時並把它轉換為一個model,去創建我們的tableview,然後把得到的對應數據展示到下半部的列表中,在點擊tableview的詳細事件中進行傳值,實現路線的規劃。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電話號碼 @property (nonatomic, strong) NSString* phone; ///POI郵編 @property (nonatomic, strong) NSString* postcode;
詳情檢索對應的協議方法
//搜索的詳細結果 - (void)onGetPoiDetailResult:(BMKPoiSearch*)searcher result:(BMKPoiDetailResult*)poiDetailResult errorCode:(BMKSearchErrorCode)errorCode{ if (errorCode == BMK_SEARCH_NO_ERROR) { //在此處理正常結果 } else if (errorCode == BMK_SEARCH_AMBIGUOUS_KEYWORD){ //當在設置城市未找到結果,但在其他城市找到結果時,回調建議檢索城市列表 // result.cityList; NSLog(@"起始點有歧義"); } else { NSLog(@"抱歉,未找到結果"); }
大頭針的自定義
我們想要自己定義我們想要看到的大頭針模樣,就要對他進行自定義。下面介紹一種簡單的處理大頭針樣式的方法,如果想要具體的根據不同的情形來進行自定義,就要進行判斷,根據他們不同的情況去給定相應的標注圖片
- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id)annotation{ BMKPinAnnotationView *newAnnotationView = [[BMKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"myAnnotation"]; newAnnotationView.pinColor = BMKPinAnnotationColorPurple; newAnnotationView.animatesDrop = NO;// 設置該標注點動畫顯示 newAnnotationView.annotation=annotation; newAnnotationView.image = [UIImage imageNamed:@"mapicon"]; //把大頭針換成別的圖片 newAnnotationView.size = CGSizeMake(20, 33); return newAnnotationView; }
後記
地圖中我們用的比較多的就是定位,POI檢索和路徑規劃了,定位的話,相信不管是官方SDK還是網上各種資料都夠詳細的了,我就不再重復了,這裡主要對路徑規劃和POI檢索做出說明,希望對大家有所幫助。
補充內容
今天有小伙伴問看了文章想知道百度地圖的模糊搜索是怎麼做的,輸入地名就能自動聯想好厲害的樣子,這裡就補充一下吧,其實也是POI搜索的一部分,是城市內搜索根據輸入的地名發起搜索,然後把搜索內容展示到tableview上罷了。如下圖:
模糊搜索.gif
當我們改變輸入框的內容時其實內部的操作是什麼呢,下面我們一點點介紹一下他。
這裡我們要做的是POI檢索,因此首先要遵循BMKPoiSearchDelegate協議,創建搜索的代碼如下:
_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;
成功之後會走下面這個協議方法
-(void)onGetPoiResult:(BMKPoiSearch *)searcher result:(BMKPoiResult *)poiResult errorCode:(BMKSearchErrorCode)errorCode
這裡我們就得到了返回的內容,然後把它裡面的數據取到轉換為模型展示到tableview上就好了,但是,為什麼是但是呢,因為你這樣做並不能得到想要的結果,因為你這裡做的檢索只是一次的,並不能實現每改變一個字就重新檢索展示出地點,我們要對輸入框做處理
[_inputFiled addTarget:self action:@selector(inputaction:) forControlEvents:UIControlEventEditingChanged];
添加事件,實現對輸入框變化的監聽,然後實現方法。
#pragma mark - 輸入框的實時監聽 -(void)inputaction:(UITextField *)textField{ [self performSelector:@selector(delay) withObject:self afterDelay:0.5]; }
這裡我們監聽輸入框的變化,然後把相應的檢索寫到delay方法中就可以了。這樣就實現了數據的展示,然後點擊對應的cell的時候,把數據傳給上個界面接Ok了啊,這裡為了用戶體驗我們可以監聽tableview的滾動,當滾動的時候讓輸入框的鍵盤消失,代碼如下:
#pragma mark -滾動隱藏鍵盤 -(void)scrollViewDidScroll:(UIScrollView *)scrollView{ [self.view endEditing:YES]; }
這樣我們就實現了模糊搜索了,是不是還是比較簡單的。有別的問題以後再接著補充吧。