前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS·采用第三方(百度地图SDK)实现定位等功能开发

iOS·采用第三方(百度地图SDK)实现定位等功能开发

作者头像
陈满iOS
发布2018-09-10 11:09:48
2K0
发布2018-09-10 11:09:48
举报
文章被收录于专栏:陈满iOS陈满iOS

1.申请密钥

首先,申请一个baidu账号,接着进入新建密钥入口申请成为baidu地图开发者,填写相关开发者信息和短信验证码。接下来点击创建应用,如官方文档新建密钥文档指南里面的截图所示,注意正确勾选有关项。如果你想要实名认证,点击页面右上角的实名状态,下面是该页面的截图。

Paste_Image.png

  • 创建应用时,注意勾选正确的应用类型

默认是服务端类型,如果没有勾选iOS SDK类型,就不能根据你自己工程BundleID(即百度地图所谓的安全码)设置Key的选项了。如图所示,创建应用没有勾选iOS SDK,当点击设置,进去后根本没有定制化的设置选项。

Paste_Image.png

  • 创建应用时,注意正确填写iOS SDK安全码

在Xcode里面,找到自己工程的安全码,即工程的Bundle Identifier,如下图所示,应该是类似com.baidu.mapdemo等格式的字符串。

Paste_Image.png

2.工程配置

2.1 CocoaPods方法

这种方法,优点是简单,不需要再对工程进行额外的配置。缺点是,没有自己根据需要选择性的加载百度开发包的余地,把整个SDK都导进来了,不管你有没有可能会用到这些包。

打开终端,输入类似下面的命令,cd到你自己工程的目录下

代码语言:javascript
复制
 $ cd /Users/ChenMan/iOSLAB/myMapDemo/

1.创建Podfile:

代码语言:javascript
复制
touch Podfile

2.编辑Podfile内容如下:

代码语言:javascript
复制
pod 'BaiduMapKit' #百度地图SDK

3.在Podfile所在的文件夹下输入命令:

代码语言:javascript
复制
pod install (这个可能比较慢,请耐心等待……)

成功以后,会出现如下记录:

代码语言:javascript
复制
Analyzing dependencies
 
Downloading dependencies
 
Installing BaiduMapKit (2.9.1)
 
Generating Pods project
 
Integrating client project
 
[!] Please close any current Xcode sessions and use `***.xcworkspace` for this project from now on.
Sending stats

恭喜你已成功导入百度地图iOS SDK,现在就可以打开xcworkspace文件,在你的项目中使用百度地图SDK了

2.2 手动拷贝依赖库方法

这种方法的优点是,可以选择性的导入所需开发包,尽可能减小APP工程体积。缺点是步骤相对繁琐,总的来说分两部分工作,一是,选择性拷贝所需开发包到工程目录下并建立引用关系(手动拖拽,并勾选copy if needed,保证所需包被复制到工程目录下,而不是仅仅是引用关系),二是,在工程的TARGETS->Build Phases-> Link Binary With Libaries里面,添加前面添加的开发包。

接下来引用百度地图的文档说明,并作了适当改编:

  • 第一步、根据需要导入 .framework包

百度地图 iOS SDK 采用分包的形式提供 .framework包,请广大开发者使用时确保各分包的版本保持一致。其中BaiduMapAPI_Base.framework为基础包,使用SDK任何功能都需导入,其他分包可按需导入

全部分包和自定义分包的下载地址为 http://lbsyun.baidu.com/index.php?title=iossdk/sdkiosdev-download,如下图所示:

这里我选择下载的是自定义分包,我只需要单纯的定位功能

注: 静态库中采用Objective-C++实现,因此需要您保证您工程中至少有一个.mm后缀的源文件(您可以将任意一个.m后缀的文件改名为.mm,比如AppDelegate.mm),或者在工程属性中指定编译方式,即在Xcode的Project -> Edit Active Target -> Build Setting 中找到 Compile Sources As,并将其设置为"Objective-C++"

  • 第二步、引入所需的系统库

百度地图SDK中提供了定位功能和动画效果,v2.0.0版本开始使用OpenGL渲染,因此您需要在您的Xcode工程中引入CoreLocation.framework和QuartzCore.framework、OpenGLES.framework、SystemConfiguration.framework、CoreGraphics.framework、Security.framework、libsqlite3.0.tbd(xcode7以前为 libsqlite3.0.dylib)、CoreTelephony.framework 、libstdc++.6.0.9.tbd(xcode7以前为libstdc++.6.0.9.dylib)

(注:粗体标识的系统库为v2.9.0新增的系统库,使用v2.9.0及以上版本的地图SDK,务必增加导入这3个系统库。)

添加方式: 在Xcode的Project -> Active Target ->Build Phases ->Link Binary With Libraries,添加这几个系统库即可。

  • 第三步、引入所需的第三方openssl库:

添加支持HTTPS所需的penssl静态库:libssl.a和libcrypto.a(SDK打好的包存放于thirdlib目录下)

例如,我需要的是单纯的定位功能,选择自定义分包下载后,会看到如下图文件目录结构,静态库:libssl.a和libcrypto.a就在thirdlibs文件夹下面。

thirdlibs文件夹

添加方法: 在 TARGETS->Build Phases-> Link Binary With Libaries中点击“+”按钮,在弹出的窗口中点击“Add Other”按钮,选择libssl.a和libcrypto.a添加到工程中

  • 第四步、环境配置

在TARGETS->Build Settings->Other Linker Flags 中添加-ObjC。

  • 第五步、引入mapapi.bundle资源文件

如果使用了基础地图功能,需要添加该资源,否则地图不能正常显示mapapi.bundle中存储了定位、默认大头针标注View及路线关键点的资源图片,还存储了矢量地图绘制必需的资源文件。如果您不需要使用内置的图片显示功能,则可以删除bundle文件中的image文件夹。您也可以根据具体需求任意替换或删除该bundle中image文件夹的图片文件。

方法:选中工程名,在右键菜单中选择Add Files to “工程名”…,从BaiduMapAPI_Map.framework||Resources文件中选择mapapi.bundle文件,并勾选“Copy items if needed”复选框,单击“Add”按钮,将资源文件添加到工程中。

  • 第六步、引入头文件

在使用SDK的类 按需 引入下边的头文件:

代码语言:javascript
复制
#import <BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件
 
#import <BaiduMapAPI_Map/BMKMapComponent.h>//引入地图功能所有的头文件
 
#import <BaiduMapAPI_Search/BMKSearchComponent.h>//引入检索功能所有的头文件
 
#import <BaiduMapAPI_Cloud/BMKCloudSearchComponent.h>//引入云检索功能所有的头文件
 
#import <BaiduMapAPI_Location/BMKLocationComponent.h>//引入定位功能所有的头文件
 
#import <BaiduMapAPI_Utils/BMKUtilsComponent.h>//引入计算工具所有的头文件
 
#import <BaiduMapAPI_Radar/BMKRadarComponent.h>//引入周边雷达功能所有的头文件
 
#import <BaiduMapAPI_Map/BMKMapView.h>//只引入所需的单个头文件

具体的应用位置,一般是两个地方,一个是AppDelegate文件,一个是调用定位功能的ViewController文件。接下来两节会讲到怎么用。

3.AppDelegate文件配置

假设我现在的需求是,APP需要定位当前所在位置经纬度,并根据经纬度反地理编码,得到所在地址,包括省市区,街道等详细地址信息。

并假设,已经申请得到了一个密钥如下(拷这个没用,自己根据BundleID申请吧):

代码语言:javascript
复制
B266f735e43ab207ec152deff44fec8b

首先,需要在AppDelegate.mm文件导入所需头文件:

代码语言:javascript
复制
//百度地图
#define BMK_KEY @"B266f735e43ab207ec152deff44fec8b"//百度地图的key
#import <BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件

其次,声明一个BMKMapManager属性:

代码语言:javascript
复制
@interface AppDelegate ()

@property (nonatomic, strong) BMKMapManager *mapManager;

@end

然后,在AppDelegate的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {}代理方法中初始化百度地图,代码如下:

代码语言:javascript
复制
    //百度地图
    _mapManager = [BMKMapManager new];
    BOOL ret = [_mapManager start:BMK_KEY generalDelegate:nil];
    if (!ret)
    {
        NSLog(@"百度地图启动失败");
    }
    else
    {
        NSLog(@"百度地图启动成功");
    }

这样,当APP启动就会启动百度地图相关模块,以便后续VC调用。

4.用到百度定位功能所在VC的配置

首先,导入相关头文件,及key的宏定义

代码语言:javascript
复制
//百度地图
#import <BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件
#import <BaiduMapAPI_Location/BMKLocationComponent.h>//引入定位功能所有的头文件
#import <BaiduMapAPI_Search/BMKSearchComponent.h>//引入检索功能所有的头文件
#define BMK_KEY @"B266f735e43ab207ec152deff44fec8b"//百度地图的key

其次,声明该VC服从百度相关模块的代理如下,其它代理自选:

代码语言:javascript
复制
//百度地图·代理
@interface TestViewController ()<UITableViewDataSource, UITableViewDelegate,CLLocationManagerDelegate,BMKGeneralDelegate,BMKLocationServiceDelegate,BMKGeoCodeSearchDelegate>
{
}

然后,声明相关属性如下:

代码语言:javascript
复制
//百度地图
@property (nonatomic, strong)BMKLocationService *locService;
@property (nonatomic, strong)BMKGeoCodeSearch *geocodesearch;
@property BOOL isGeoSearch;

接着,在VC的- (void)viewDidLoad {}方法里面,对相关模块进行初始化操作。

代码语言:javascript
复制
    //百度地图
    //启动LocationService
    _locService = [[BMKLocationService alloc]init];//定位功能的初始化
    _locService.delegate = self;//设置代理位self
    [_locService startUserLocationService];//启动定位服务

最后,实现百度地图相关代理方法,并进行自定义的一些操作。

代码语言:javascript
复制
#pragma mark - BMK_LocationDelegate 百度地图
/**
 *定位失败后,会调用此函数
 *@param error 错误号
 */
- (void)didFailToLocateUserWithError:(NSError *)error
{
    NSLog(@"地图定位失败======%@",error);
}

//处理位置坐标更新
- (void)didUpdateBMKUserLocation:(BMKUserLocation *)userLocation
{
    NSLog(@"didUpdateUserLocation lat %f,long %f",userLocation.location.coordinate.latitude,
          userLocation.location.coordinate.longitude);
    
    //从manager获取左边
    CLLocationCoordinate2D coordinate = userLocation.location.coordinate;//位置坐标
    //存储经纬度
    [self.userLocationInfoModel SaveLocationCoordinate2D:coordinate];
    
    if ((userLocation.location.coordinate.latitude != 0 || userLocation.location.coordinate.longitude != 0))
    {
        
        
        //发送反编码请求
        //[self sendBMKReverseGeoCodeOptionRequest];
        
        NSString *latitude = [NSString stringWithFormat:@"%f",userLocation.location.coordinate.latitude];
        NSString *longitude = [NSString stringWithFormat:@"%f",userLocation.location.coordinate.longitude];
        [self reverseGeoCodeWithLatitude:latitude withLongitude:longitude];
        
    }else{
        NSLog(@"位置为空");
    }
    
    //关闭坐标更新
    [self.locService stopUserLocationService];
}

//地图定位
- (BMKLocationService *)locService
{
    if (!_locService)
    {
        _locService = [[BMKLocationService alloc] init];
        _locService.delegate = self;
    }
    return _locService;
}

//检索对象
- (BMKGeoCodeSearch *)geocodesearch
{
    if (!_geocodesearch)
    {
        _geocodesearch = [[BMKGeoCodeSearch alloc] init];
        _geocodesearch.delegate = self;
    }
    return _geocodesearch;
}

#pragma mark ----反向地理编码
- (void)reverseGeoCodeWithLatitude:(NSString *)latitude withLongitude:(NSString *)longitude
{
    
    //发起反向地理编码检索
    
    CLLocationCoordinate2D coor;
    coor.latitude = [latitude doubleValue];
    coor.longitude = [longitude doubleValue];
    
    BMKReverseGeoCodeOption *reverseGeocodeSearchOption = [[BMKReverseGeoCodeOption alloc] init];
    reverseGeocodeSearchOption.reverseGeoPoint = coor;
    BOOL flag = [self.geocodesearch reverseGeoCode:reverseGeocodeSearchOption];;
    if (flag)
    {
        NSLog(@"反地理编码成功");//可注释
    }
    else
    {
        NSLog(@"反地理编码失败");//可注释
    }
}

//发送反编码请求
- (void)sendBMKReverseGeoCodeOptionRequest{
    
    self.isGeoSearch = false;
    CLLocationCoordinate2D pt = (CLLocationCoordinate2D){0, 0};//初始化
    if (_locService.userLocation.location.coordinate.longitude!= 0
        && _locService.userLocation.location.coordinate.latitude!= 0) {
        //如果还没有给pt赋值,那就将当前的经纬度赋值给pt
        pt = (CLLocationCoordinate2D){_locService.userLocation.location.coordinate.latitude,
            _locService.userLocation.location.coordinate.longitude};
    }
    
    BMKReverseGeoCodeOption *reverseGeocodeSearchOption = [[BMKReverseGeoCodeOption alloc]init];//初始化反编码请求
    reverseGeocodeSearchOption.reverseGeoPoint = pt;//设置反编码的店为pt
    BOOL flag = [_geocodesearch reverseGeoCode:reverseGeocodeSearchOption];//发送反编码请求.并返回是否成功
    if(flag)
    {
        NSLog(@"反geo检索发送成功");
    }
    else
    {
        NSLog(@"反geo检索发送失败");
    }
}


//发送成功,百度将会返回东西给你
-(void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher
                           result:(BMKReverseGeoCodeResult *)result
                        errorCode:(BMKSearchErrorCode)error
{
    
    if (error == BMK_SEARCH_NO_ERROR) {
        NSString *address1 = result.address; // result.addressDetail ///层次化地址信息
        NSLog(@"我的位置在 %@",address1);
        
        //保存位置信息到模型
        [self.userLocationInfoModel saveLocationInfoWithBMKReverseGeoCodeResult:result];
        
        //进行缓存处理,上传到服务器等操作
}

需要提到的是,可以合理利用BMKReverseGeoCodeResult类型的对象result,比如取出它的某些属性存到自己定义的模型中去。该对象的类型是百度地图SDK的类,里面包含了根据经纬度返回的地址信息。它的类文件如下:

代码语言:javascript
复制
/*
 *  BMKGeocodeType.h
 *  BMapKit
 *
 *  Copyright 2011 Baidu Inc. All rights reserved.
 *
 */

#import <BaiduMapAPI_Base/BMKTypes.h>

///反地址编码结果
@interface BMKReverseGeoCodeResult : NSObject
{
    BMKAddressComponent* _addressDetail;
    NSString* _address;
    CLLocationCoordinate2D _location;
    NSArray* _poiList;
}
///层次化地址信息
@property (nonatomic, strong) BMKAddressComponent *addressDetail;
///地址名称
@property (nonatomic, strong) NSString* address;
///商圈名称
@property (nonatomic, strong) NSString* businessCircle;
///结合当前位置POI的语义化结果描述
@property (nonatomic, strong) NSString* sematicDescription;
///地址坐标
@property (nonatomic) CLLocationCoordinate2D location;
///地址周边POI信息,成员类型为BMKPoiInfo
@property (nonatomic, strong) NSArray* poiList;

@end

///地址编码结果
@interface BMKGeoCodeResult : NSObject
{
    CLLocationCoordinate2D _location;
    NSString* _address;
}
///地理编码位置
@property (nonatomic) CLLocationCoordinate2D location;
///地理编码地址
@property (nonatomic,strong) NSString* address;

@end

其中,result对象包含了一个层次化地址信息,如@property (nonatomic, strong) BMKAddressComponent *addressDetail;所示。它的addressDetail属性包含的信息可从BMKAddressComponent类的代码了解更多:

代码语言:javascript
复制
///线路检索节点信息,一个路线检索节点可以通过经纬度坐标或城市名加地名确定
@interface BMKPlanNode : NSObject{
    NSString*              _cityName;
    NSString*              _name;
    CLLocationCoordinate2D _pt;
}

///节点所在城市
@property (nonatomic, strong) NSString* cityName;
///节点所在城市ID
@property (nonatomic, assign) NSInteger cityID;
///节点名称
@property (nonatomic, strong) NSString* name;
///节点坐标
@property (nonatomic) CLLocationCoordinate2D pt;
@end

///室内路线检索节点信息
@interface BMKIndoorPlanNode : NSObject

///节点所在楼层
@property (nonatomic, retain) NSString* floor;
///节点坐标
@property (nonatomic) CLLocationCoordinate2D pt;

@end

///此类表示地址结果的层次化信息
@interface BMKAddressComponent : NSObject

/// 街道号码
@property (nonatomic, strong) NSString* streetNumber;
/// 街道名称
@property (nonatomic, strong) NSString* streetName;
/// 区县名称
@property (nonatomic, strong) NSString* district;
/// 城市名称
@property (nonatomic, strong) NSString* city;
/// 省份名称
@property (nonatomic, strong) NSString* province;
/// 国家
@property (nonatomic, strong) NSString* country;
/// 国家代码
@property (nonatomic, strong) NSString* countryCode;

@end

正如上面的代码中看到,里面包含了国家,省市区,街道及街道号等层次化信息。在实际的开发中,可以按需取出这些信息,这种操作可以写在下面的代理方法中去。

代码语言:javascript
复制
//发送成功,百度将会返回东西给你
-(void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher
                           result:(BMKReverseGeoCodeResult *)result
                        errorCode:(BMKSearchErrorCode)error
{
   //取出层次化信息操作
}

附1:可能的问题

百度地图反geo检索发送失败

可能因为,key是其它样例Demo的,或者以前申请的过期了。检查一下,用自己工程的Bundle Identifer重新申请key,在真机上进行测试,反检索发起成功。这时候需要重新申请密钥key。

  • 新建密钥入口 http://lbsyun.baidu.com/apiconsole/key

附2:参考文献

  1. 百度地图iOS SDK开发指南
  2. 百度地图iOS地图SDK
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.05.01 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.申请密钥
  • 2.工程配置
  • 3.AppDelegate文件配置
  • 4.用到百度定位功能所在VC的配置
    • 附1:可能的问题
      • 附2:参考文献
      相关产品与服务
      短信
      腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档