項目最近對地圖總體模塊進行了重構, 爲了和咱們的安卓同窗保持統一,放棄了本來就很6的高德地圖,所有改用百度地圖(雖然我以爲百度地圖很差用,文檔也通常,可是沒辦法啊,沒辦法啊 啊啊啊啊啊..).git
項目中用到的百度地圖的主要功能點有如下幾個:c#
在實際的使用過程當中這些功能可能會有交叉,因此代碼會整個貼過來,下面就根據實際功能需求一一介紹.數組
地圖的初始化:微信
- (void)initMapView { self.mapView = [[BMKMapView alloc] initWithFrame:CGRectMake(0, 44, SCREEN_WIDTH, SCREEN_WIDTH/372*253)]; self.mapView.showsUserLocation = YES; self.mapView.userTrackingMode = BMKUserTrackingModeNone; self.mapView.gesturesEnabled = YES; self.mapView.zoomEnabled = YES; self.mapView.maxZoomLevel = 23; self.mapView.zoomLevel = 16; // 顯示比例尺 200m (和微信同樣....) self.mapView.showMapScaleBar = YES; // 回到當前位置按鈕 UIButton *showUserLocation = [[UIButton alloc] initWithFrame:CGRectMake(self.mapView.mj_width - 21 - 50, self.mapView.mj_height - 21 - 50, 50, 50)]; [self.mapView addSubview:showUserLocation]; [showUserLocation addTarget:self action:@selector(backToCurrentLocation) forControlEvents:UIControlEventTouchUpInside]; [showUserLocation setBackgroundImage:[UIImage imageNamed:@"showuserlocation"] forState:UIControlStateNormal]; UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.mapView.mj_width * 0.5 - 8, self.mapView.mj_height * 0.5 - 40, 16, 40)]; imageView.image = [UIImage imageNamed:@"datouzhen"]; imageView.contentMode = UIViewContentModeScaleAspectFit; [self.mapView addSubview:imageView]; [self.view addSubview:self.mapView]; }
這裏提醒一點百度地圖各項服務的delegate須要在 viewWillApper設置爲self,viewWillDisapper時設置爲nil,不然的話會出現內存泄露.app
如下是定位成功後的回調方法ide
/** *用戶位置更新後,會調用此函數 *@param userLocation 新的用戶位置 */ - (void)didUpdateBMKUserLocation:(BMKUserLocation *)userLocation { [self.mapView updateLocationData:userLocation]; CLLocation *location = userLocation.location; // 若是不是區域檢索 if (!(self.city.length > 0)) { // 設置當前位置爲地圖的中心點 NSLog(@"%f-----%f",userLocation.location.coordinate.latitude,userLocation.location.coordinate.longitude); [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude) animated:YES]; } self.currentCoor = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude); // 定位成功會後 if (location) { [self.locationService stopUserLocationService]; // 反向編碼 [self beginReverseGeoCodeSearch]; } }
這裏進行了判斷,若是不是區域檢索(若是我人在北京,可是要讓地圖顯示是石家莊市 此時須要用到區域檢索),則將當前定位到的位置設置爲地圖的中心點 . 而後開始進行反地理編碼.函數
由於在發佈分享的時候有一個選項顯示的是當前所在的城市,以下圖一,二 . 第二個cell顯示的 "北京市" 因此須要進行反地理編碼.ui
反地理編碼成功後的回調:編碼
// 反地理編碼回調 - (void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKReverseGeoCodeResult *)result errorCode:(BMKSearchErrorCode)error { // result ->poiList ///地址周邊POI信息,成員類型爲BMKPoiInfo // @property (nonatomic, strong) NSArray* poiList; if (result.poiList.count > 0) { self.currentPoiInfo = [result.poiList firstObject]; } // 反向地理編碼成功後 ,進行poi搜索 [self beginPoiSearch:self.currentCoor keyword:@""]; }
三.poi 檢索atom
百度地圖poi只能設置一個關鍵字(也有多是我沒找到方法,若是能夠設置多個請及時聯繫,謝謝)
發起poi檢索
#pragma mark ----發起檢索 // 發起poi檢索 - (void)beginPoiSearch:(CLLocationCoordinate2D)coor keyword:(NSString *)keyowrd{ BMKNearbySearchOption *option = [[BMKNearbySearchOption alloc]init]; option.pageCapacity = 50; // 按距離排序 option.sortType = BMK_POI_SORT_BY_DISTANCE; // 以地圖中心點爲座標發起檢索 默認keyword 寫字樓 option.location = CLLocationCoordinate2DMake(coor.latitude, coor.longitude); option.keyword = keyowrd.length > 0 ? keyowrd : @"寫字樓"; BOOL flag = [self.poiSearch poiSearchNearBy:option]; NSLog(@"%@",flag ? @"周邊檢索發送成功" : @"周邊檢索發送失敗"); }
poi檢索發起成功後的頁面展現以下圖:
圖 一 圖 二
這裏除了poi檢索以外,還加了一個地圖中心點功能,及拖動地圖的時候以大頭針的位置爲當前地圖的中心點,而後再進行poi檢索.這裏須要監聽另一個回調方法.
// 拖拽地圖的回調 - (void)mapView:(BMKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { [self beginPoiSearch:self.mapView.centerCoordinate keyword:self.keyword.length > 0 ? self.keyword : @""]; }
在這個回調方法中,以當前地圖的中心爲poi檢索的中心點 發起poi檢索.
搜搜建議功能截圖以下圖:
在serchDisplayController的代理方法中發送搜索建議的請求:
#pragma mark ---displayControllerDelegate - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { self.searchText = searchString; self.suggestSearch = [[BMKSuggestionSearch alloc]init]; self.suggestSearch.delegate = self; BMKSuggestionSearchOption* option = [[BMKSuggestionSearchOption alloc] init]; option.cityname = self.city; option.keyword = searchString; BOOL flag = [self.suggestSearch suggestionSearch:option]; NSLog(@"%@",flag ? @"建議檢索發送成功" : @"建議檢索發送失敗"); return YES; }
而後在其回調方法中處理搜索建議結果:
// 搜索建議返回的關鍵詞list和區list ,coor list,poi id list @property (nonatomic,strong)NSMutableArray *keyList; // 萬達廣場 @property (nonatomic,strong)NSMutableArray *districtList; // 海淀區 @property (nonatomic,strong)NSMutableArray *coorList; // coor 包裝成的 NSValue對象 @property (nonatomic,strong)NSMutableArray *poiuIdList; // poi id - (void)onGetSuggestionResult:(BMKSuggestionSearch *)searcher result:(BMKSuggestionResult *)result errorCode:(BMKSearchErrorCode)error { self.keyList = [NSMutableArray arrayWithCapacity:0]; self.districtList = [NSMutableArray arrayWithCapacity:0]; self.coorList = [NSMutableArray arrayWithCapacity:0]; self.poiuIdList = [NSMutableArray arrayWithCapacity:0]; NSMutableArray *emptyLocationArray = [NSMutableArray arrayWithCapacity:0]; for (int i = 0; i<result.ptList.count; i++) { CLLocationCoordinate2D coor; NSValue *coorValue = result.ptList[i]; [coorValue getValue:&coor]; // 非空的地址加到數組中 if (!((int)coor.latitude == 0 && (int)coor.longitude == 0)) { [emptyLocationArray addObject:[NSString stringWithFormat:@"%d",i]]; [self.keyList addObject:result.keyList[i]]; [self.districtList addObject:result.districtList[i]]; [self.coorList addObject:result.ptList[i]]; [self.poiuIdList addObject:result.poiIdList[i]]; } } [self.displayController.searchResultsTableView reloadData]; }
點擊搜索建議tableView的cell時,須要mapView跳轉到對應的位置,並搜索其附近對應的poi信息(好比我點的結果是個餐廳,那麼就地圖就滾動到這個餐廳的位置,並以"餐飲"爲關鍵詞搜索附近的poi信息),因此這裏須要用到另一個接口:poi詳情搜索(注意是poi詳情搜索,兩個有點像)
點擊cell時,根據poi 的id發起poi詳情搜索 :
// 發起poi 詳情檢索 - (void)beginPoiDetailSearch:(NSString *)uid { BMKPoiDetailSearchOption* option = [[BMKPoiDetailSearchOption alloc] init]; option.poiUid = uid;//POI搜索結果中獲取的uid BOOL flag = [self.poiSearch poiDetailSearch:option]; NSLog(@"%@",flag ? @"POI詳情檢索發送成功" : @"POI詳情檢索發送失敗"); }
poi詳情檢索成功後的回調:
- (void)onGetPoiDetailResult:(BMKPoiSearch *)searcher result:(BMKPoiDetailResult *)poiDetailResult errorCode:(BMKSearchErrorCode)errorCode { CLLocationCoordinate2D coor; NSValue *coorValue = self.coorList[self.searchResultSelectedIndexPath.row]; [coorValue getValue:&coor]; self.keyword = poiDetailResult.tag; // 改變中心座標 [self.mapView setCenterCoordinate:coor animated:YES]; [self beginPoiSearch:coor keyword:poiDetailResult.tag]; }
返回的結果是 BMKPoiDetailResult 對象,裏面包含了 poi的詳細信息,包括 name address tag(poi標籤)等.
而後以 poiDetailResult.tag 爲關鍵字進行poi搜索.
我人在北京,可是想查看石家莊的景點,小吃等信息 . 此時就須要用到區域檢索功能了. 先判斷
if (self.city.length > 0) {
[self beginDistrictSearch];
} 若是傳過來的城市的名字長度大於 0 則說明要先進行區域檢索.
// 發起區域檢索 - (void)beginDistrictSearch { //初始化檢索對象 self.districtSearch = [[BMKDistrictSearch alloc] init]; //設置delegate,用於接收檢索結果 self.districtSearch.delegate = self; //構造行政區域檢索信息類 BMKDistrictSearchOption *option = [[BMKDistrictSearchOption alloc] init]; option.city = self.city; option.district = self.district; //發起檢索 BOOL flag = [self.districtSearch districtSearch:option]; NSLog(@"%@",flag ? @"區域檢索發送成功" : @"區域檢索發送失敗"); }
區域檢索成功後的回調:
- (void)onGetDistrictResult:(BMKDistrictSearch *)searcher result:(BMKDistrictResult *)result errorCode:(BMKSearchErrorCode)error { NSLog(@"---->%f----%f",result.center.latitude,result.center.longitude); // 設置地圖中心點 [self.mapView setCenterCoordinate:result.center animated:YES]; // 以城市中心點爲中心發起poi檢索 [self beginPoiSearch:result.center keyword:@""]; }
這樣就能夠實現檢索不一樣省份城市的 poi信息了.
效果以下圖:
點擊上面導航按鈕會進行判斷,判斷當前app是否安裝了高德,百度以及蘋果自帶的地圖 若是有則將其展現出來不然則不顯示. 點擊以後則會調起對應的地圖進行導航,具體實現能夠看我這篇博客 iOS經過URL調起第三方地圖進行導航
效果以下圖:
點擊大頭針彈出pop ,這裏的pop是本身繪製的代碼:
@interface BubbleView : UIView @end @implementation BubbleView - (void)drawRect:(CGRect)rect { [super drawRect:rect]; CGFloat width = rect.size.width; CGFloat height = rect.size.height; CGFloat radius = 5; CGFloat jianjiaoH = 12; // 獲取CGContext,注意UIKit裏用的是一個專門的函數 CGContextRef context = UIGraphicsGetCurrentContext(); // 移動到初始點 CGContextMoveToPoint(context, radius, 0); // 繪製第1條線和第1個1/4圓弧 CGContextAddLineToPoint(context, width - radius, 0); CGContextAddArc(context, width - radius, radius, radius, -0.5 * M_PI, 0.0, 0); // CGContextAddArc(<#CGContextRef _Nullable c#>, <#CGFloat x#>, <#CGFloat y#>, <#CGFloat radius#>, <#CGFloat startAngle#>, <#CGFloat endAngle#>, <#int clockwise#>) // 繪製第2條線和第2個1/4圓弧 17 CGContextAddLineToPoint(context, width, height - radius - jianjiaoH); CGContextAddArc(context, width - radius, height - radius - jianjiaoH, radius, 0.0, 0.5 * M_PI, 0); // 繪製第3條線和第3個1/4圓弧和尖角 CGContextAddLineToPoint(context, width/2 + 9, height - jianjiaoH); CGContextAddLineToPoint(context, width/2, height); CGContextAddLineToPoint(context, width/2 - 9, height - jianjiaoH); CGContextAddLineToPoint(context, width - radius, height - jianjiaoH); CGContextAddArc(context, radius, height - radius - jianjiaoH, radius, 0.5 * M_PI, M_PI, 0); // 繪製第4條線和第4個1/4圓弧 CGContextAddLineToPoint(context, 0, radius); CGContextAddArc(context, radius, radius, radius, M_PI, 1.5 * M_PI, 0); // 閉合路徑 CGContextClosePath(context); // 填充半透明黑色 CGContextSetRGBFillColor(context, 0, 0, 0.0, 0.5); CGContextDrawPath(context, kCGPathFill); } @end
至此,這次咱們用的百度地圖的功能已經所有分享給你們了,若是紕漏請指正 .所有的代碼我貼在動彈裏了 -_-