iOS百度地图的使用

你离开我真会死。 提交于 2020-03-02 00:58:15

    项目最近对地图整体模块进行了重构, 为了和我们的安卓同学保持统一,放弃了原本就很6的高德地图,全部改用百度地图(虽然我觉得百度地图不好用,文档也一般,但是没办法啊,没办法啊 啊啊啊啊啊..).

项目中用到的百度地图的主要功能点有以下几个:

  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,否则的话会出现内存泄露.

以下是定位成功后的回调方法

/**
 *用户位置更新后,会调用此函数
 *@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显示的 "北京市" 所以需要进行反地理编码.

反地理编码成功后的回调:

// 反地理编码回调
- (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 检索

百度地图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

至此,此次我们用的百度地图的功能已经全部分享给大家了,如果纰漏请指正 .全部的代码我贴在动弹里了 -_-

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!