iOS 百度地图实现模糊搜索和定位、跳转本机地图 上
2017-07-09 本文已影响1534人
Bales_chu
前言
项目中要集成百度地图,百度的api文档写的很乱,说一下我们项目需求,我们有两个界面需要用到百度地图。
1.一个需要点击地理位置在地图上搜索定位。
2.另一个类似于微信发朋友圈输入关键词模糊搜索地理位置信息
<br />
开发过程中遇到的问题先跟大家分享一下,我在导入百度地图之后,跳转到地图界面不能滑动不能缩放,心里很纳闷,而且我也没有在这里用到手势缩放、和一些带滑动的控制器呀,后来我看上个控制器我发现我把 这个控制器imageVIew和他上边的一些按钮整到 window最上层,控制器结束了跳转到这个界面之后imageView还在Window最上层上,所以你创建的地图就相当于一个在image上当然不可能拖动。所以对于这种问题要向相似的地方想,很快就能找到问题的所在。
<br />
搜索定位调起本机地图.gif
<br />
类似微信模糊搜索.gif<br />
定位功能的实现步骤
1.配置环境
建议使用cocoaPods,这样减少好多无用功
2.在delegate设置AppKey、创建百度manager
如果你导入的第三方太多导致APPdelegate代码太多,你也可以把各个第三方在delegate里边的内容用类的类别分成一个一个的这样比较好管理.
.h 文件
#import "AppDelegate.h"
#import <BaiduMapAPI_Base/BMKMapManager.h>
@interface AppDelegate (BaiDu)
- (void)initBaiduMapApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
@end
.m文件
#import "AppDelegate+BaiDu.h"
@implementation AppDelegate (BaiDu)
- (void)initBaiduMapApplication:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
//创建并初始化一个引擎对象
BMKMapManager *manager = [[BMKMapManager alloc] init];
//启动地图引擎
BOOL success = [manager start:@"LV7PXGmnzecWjEZZ9leZADGUoYXeaVzd" generalDelegate:nil];
if (!success) {
NSLog(@"失败");
}
// Override point for customization after application launch.
}
然后在APPdelegate里边调用这个方法就行了
<br />
3.在相应的 controller 里边导入需要的头文件、设置百度地图的代理
#import "TJLocationMapViewController.h"
/***
<自己定义的大头针>
****/
#import "mapMark.h"
/***
<最下边的点击调起本机地图视图>
****/
#import "TJGuideView.h"
/***
<系统地图头文件>
****/
#import <MapKit/MapKit.h>
#import <BaiduMapAPI_Map/BMKMapView.h>
#import <BaiduMapAPI_Map/BMKMapComponent.h>
#import <BaiduMapAPI_Location/BMKLocationComponent.h>
#import <BaiduMapAPI_Search/BMKSearchComponent.h>
@interface TJLocationMapViewController ()<BMKMapViewDelegate,BMKLocationServiceDelegate,BMKPoiSearchDelegate,UIActionSheetDelegate>
@property (nonatomic,strong) BMKMapView *mapView;//地图视图
@property (nonatomic,strong) BMKLocationService *locationService;//定位服务
@property (nonatomic,strong)BMKPoiSearch *poiSearch;
@property (nonatomic , strong)NSMutableArray *dataArr;
/***
<存储地图定位自己和目标位置坐标>
***/
@property (nonatomic)CLLocationCoordinate2D beginingCoordinate;
@property (nonatomic)CLLocationCoordinate2D destinationCoordinate;
/***
<存储定位地图的位置名称>
***/
@property (nonatomic , strong)NSString *myNameStr;
@property (nonatomic , strong)NSString *toNameStr;
/***
<返回到上个控制器的button和点击回到自己位置的button>
***/
@property (nonatomic , strong)UIButton *backBtn;
@property (nonatomic , strong)UIButton *backToMyselfLocatinBtn;
@property (nonatomic , strong)TJGuideView *guideView;
@end
<br />
注:前三步看百度文档应该没问题,好了预备工作做完了下面开始写基本功能了
4.创建_mapView、_locationService、_poiSearch并且在-(void)viewWillAppear:(BOOL)animated、-(void)viewWillDisappear:(BOOL)animated里边设置和取消他们的代理,设置地图的一些基本信息
<br />
创建 mapView
self.mapView = [[BMKMapView alloc]initWithFrame:CGRectMake(0, 0, ScreenWidth, SCREEN_HEIGHT - 105*ADAPTERWIDTH)];
/****
地图样式
***/
self.mapView.mapType = BMKMapTypeStandard;
self.mapView.userTrackingMode = BMKUserTrackingModeNone;
self.mapView.scrollEnabled = YES;
self.mapView.showsUserLocation = YES;
//在手机上当前可使用的级别为3-21级
self.mapView.zoomLevel = 18;
/***
<定位服务>
****/
_locationService = [[BMKLocationService alloc] init];
_locationService.distanceFilter = 10.f;
_locationService.desiredAccuracy = kCLLocationAccuracyBest;
[_locationService startUserLocationService];//开始定位
[self.view addSubview:self.mapView];
设置取消代理
-(void)viewWillAppear:(BOOL)animated
{
[_mapView viewWillAppear];
self.navigationController.navigationBar.hidden = YES;
_mapView.delegate = self; // 此处记得不用的时候需要置nil,否则影响内存的释放
_poiSearch.delegate = self;
_locationService.delegate = self;
}
-(void)viewWillDisappear:(BOOL)animated
{
[_mapView viewWillDisappear];
[self.navigationController setNavigationBarHidden:NO animated:YES];
_mapView.delegate = nil; // 不用时,置nil
_poiSearch.delegate = nil;
_locationService.delegate = nil;
}
<br />
5.一些代理方法的实现
#pragma mark - BMK Location delegate
/***
<定位>
***/
-(void)didUpdateBMKUserLocation:(BMKUserLocation *)userLocation{
CLLocation *location = userLocation.location;
mapMark *nowAnno = [[mapMark alloc] init];
nowAnno.coordinate = location.coordinate;
nowAnno.title = @"我的位置";
nowAnno.type = 0;
[self.mapView addAnnotation:nowAnno];
BMKCoordinateSpan span;
span.latitudeDelta = 0.5;
span.longitudeDelta = 0.5;
BMKCoordinateRegion region;
region.center = location.coordinate;
region.span = span;
[self.mapView setRegion:region animated:YES];
//停止定位
[_locationService stopUserLocationService];
//检索
[self addBMKCloudSearchWith:userLocation];
}
- (void)addBMKCloudSearchWith:(BMKUserLocation *)userLocation{
// 初始化云检索服务
_poiSearch = [[BMKPoiSearch alloc] init];
_poiSearch.delegate = self;
// 设置地图级别
[self.mapView setZoomLevel:17];
self.mapView.isSelectedAnnotationViewFront = YES; //设定是否总让选中的annotaion置于最前面
BMKNearbySearchOption * option = [[BMKNearbySearchOption alloc]init];
/***
<这个值本来是传过来的不是固定的,我这里写的固定是方便大家看>
***/
option.keyword = @"成都市金牛区万达广场";
option.location = userLocation.location.coordinate;
self.beginingCoordinate = option.location;
NSLog(@"option.loction == %f %f", self.beginingCoordinate.latitude, self.beginingCoordinate.longitude);
option.radius = 10000;
/***
<因为我需要一个定位所以我就拿一个位置的信息>
***/
option.pageCapacity = 1;
BOOL flag = [_poiSearch poiSearchNearBy:option];
if (flag) {
NSLog(@"检索发送成功");
}else{
NSLog(@"检索发送失败");
}
}
#pragma mark implement BMKSearchDelegate
/***
<检索数据回调,数据都在BMKPoiResult里边,拿出来想怎么用都行>
***/
- (void)onGetPoiResult:(BMKPoiSearch *)searcher result:(BMKPoiResult*)result errorCode:(BMKSearchErrorCode)error{
if (error == BMK_SEARCH_NO_ERROR) {
NSMutableArray *annotations = [NSMutableArray array];
result.currPoiNum = 1;
for (int i = 0; i < result.poiInfoList.count; i++) {
BMKPoiInfo* poi = [result.poiInfoList objectAtIndex:i];
mapMark* item = [[mapMark alloc]init];
item.coordinate = poi.pt;
self.destinationCoordinate = item.coordinate;
NSLog(@"%f %f", self.destinationCoordinate.longitude , self.destinationCoordinate.latitude);
item.title = poi.name;
NSLog(@"self.title%@",item.title);
item.type = 1;
[self.dataArr addObject:poi];
[annotations addObject:item];
}
[self.mapView addAnnotations:annotations];//添加大头针
[self.mapView showAnnotations:annotations animated:YES];//显示
} else if (error == BMK_SEARCH_PERMISSION_UNFINISHED){
NSLog(@"用户没有授权");
}else{
NSLog(@"检索失败:%d",error);
}
}
<br />
6.添加大头针
/***
<大头针>
***/
- (BMKAnnotationView *)mapView:(BMKMapView *)view viewForAnnotation:(id <BMKAnnotation>)annotation{
if ([annotation isKindOfClass:[mapMark class]]) {
mapMark *anno = (mapMark *)annotation;
// 生成重用标示identifier
NSString *AnnotationViewID = @"xidanMark";
// 检查是否有重用的缓存
BMKAnnotationView* annotationView = [view dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];
// 缓存没有命中,自己构造一个,一般首次添加annotation代码会运行到此处
if (annotationView == nil) {
annotationView = [[BMKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID];
if (anno.type == 0) {
((BMKPinAnnotationView*)annotationView).pinColor = BMKPinAnnotationColorPurple;
}else if (anno.type == 1){
((BMKPinAnnotationView*)annotationView).pinColor = BMKPinAnnotationColorRed;
}
// 设置重天上掉下的效果(annotation)
((BMKPinAnnotationView*)annotationView).animatesDrop = YES;
}
// 设置位置
annotationView.centerOffset = CGPointMake(0, -(annotationView.frame.size.height * 0.5));
annotationView.annotation = annotation;
annotationView.canShowCallout = YES;
[self.mapView selectAnnotation:anno animated:YES];
// 设置是否可以拖拽
annotationView.draggable = NO;
return annotationView;
}
return nil;
}
好了基本的定位功能就实现了
<br />
下边就是实现点击回到自己位置功能和调起本机地图功能
1.点击回到自己位置
其实这个功能很简单,只要拿到自己的位置数据,只需要把自己的位置再次设置到地图中心点就行了.
/***
<点击回到自己的位置>
***/
-(void)backToMyselfLocatin:(UIButton *)sender{
BMKCoordinateRegion region ;//表示范围的结构体
//设置自己为中心点
region.center = self.beginingCoordinate;//中心点
region.span.latitudeDelta = 0.01;//经度范围(设置为0.1表示显示范围为0.2的纬度范围)
region.span.longitudeDelta = 0.01;//纬度范围
[_mapView setRegion:region animated:YES];
}
2.调起本机地图
我只写主要代码就好了,苹果地图使用option就行了不用 URL 调起,而百度地图需要配置URL才能调起不过性质大概都一样
<br />
调起百度地图
//主要是配置自己和目的地的一些左边参数,另外百度地图如果那个mode参数里边你不加经纬度格式参数的话它默认就是百度地图用的参数,加的话记得要和百度地图的一致
NSString *url = [[NSString stringWithFormat:@"baidumap://map/direction?origin=latlng:%f,%f|name:我的位置&destination=latlng:%f,%f|name:%@&mode=driving®ion=成都",self.beginingCoordinate.longitude, self.beginingCoordinate.latitude,self.destinationCoordinate.longitude,self.destinationCoordinate.latitude,@"成都市万达广场"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] ;
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"baidumap://map/"]])
{
if ([[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]] == NO)
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms://itunes.apple.com/cn/app/百度地图-智能的手机导航-公交地铁出行必备/id452186370?mt=8"]];
}
}else{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms://itunes.apple.com/cn/app/百度地图-智能的手机导航-公交地铁出行必备/id452186370?mt=8"]];
}
<br />
调起苹果地图
MKMapItem *currentLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake((self.beginingCoordinate.latitude),(self.beginingCoordinate.longitude)) addressDictionary:nil]];
currentLocation.name =@"我的位置";
//目的地的位置
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:self.destinationCoordinate addressDictionary:nil]];
toLocation.name = @"成都万达广场";
NSArray *items = [NSArray arrayWithObjects:currentLocation, toLocation, nil];
NSDictionary *options = @{ MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsMapTypeKey: [NSNumber numberWithInteger:MKMapTypeStandard], MKLaunchOptionsShowsTrafficKey:@YES };
//打开苹果自身地图应用,并呈现特定的item
[MKMapItem openMapsWithItems:items launchOptions:options];
<br />