项目最近对地图总体模块进行了重构, 为了和咱们的安卓同窗保持统一,放弃了本来就很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
至此,这次咱们用的百度地图的功能已经所有分享给你们了,若是纰漏请指正 .所有的代码我贴在动弹里了 -_-