路徑規劃.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,然後我們根據模型中的資料地點或者經緯度,可以規劃處我們所在地到目的地的線路規劃,一樣有駕車,公交,步行,三種。這裡不得不吐槽一下為啥那麼多電話都沒有嘞。
IMG_0003.PNG
IMG_0004.PNG
我們要進行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<BMKAnnotation>)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];
}