iOS

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&region=成都",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 />

楼主一周休息一天,能在周末早上爬起来写这个也是挺心疼自己的,楼主不单身,但是楼主爱工作,注释什么的都是新加上去的,还有定义的 frame 因为自己封装的约束所以重新改了才贴的代码,喜欢的能给个赞就好了。
关于百度地图模糊搜索的我下午写出来,我写的有什么不清楚的可以在评论里说,我每天都会看的
上一篇下一篇

猜你喜欢

热点阅读