iOS百度地圖的使用

    項目最近對地圖總體模塊進行了重構, 爲了和咱們的安卓同窗保持統一,放棄了本來就很6的高德地圖,所有改用百度地圖(雖然我以爲百度地圖很差用,文檔也通常,可是沒辦法啊,沒辦法啊 啊啊啊啊啊..).git

項目中用到的百度地圖的主要功能點有如下幾個:c#

  1. 基礎地圖和定位
  2. 反地理編碼功能
  3. poi檢索
  4. 搜索建議和poi詳情檢索
  5. 區域檢索功能
  6. 經過url調起第三方地圖進行
  7. 自定義彈出泡泡

 在實際的使用過程當中這些功能可能會有交叉,因此代碼會整個貼過來,下面就根據實際功能需求一一介紹.數組

一.基礎地圖和定位功能

地圖的初始化:微信

- (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檢索.

四.搜索建議功能和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信息了.

六.經過url調起第三方地圖進行

效果以下圖:

      

點擊上面導航按鈕會進行判斷,判斷當前app是否安裝了高德,百度以及蘋果自帶的地圖 若是有則將其展現出來不然則不顯示. 點擊以後則會調起對應的地圖進行導航,具體實現能夠看我這篇博客 iOS經過URL調起第三方地圖進行導航

七.自定義彈出pop

效果以下圖:

點擊大頭針彈出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

至此,這次咱們用的百度地圖的功能已經所有分享給你們了,若是紕漏請指正 .所有的代碼我貼在動彈裏了 -_-

相關文章
相關標籤/搜索