文章原地址:http://lipengxuan.easymorse.com/?p=526
由于没有转发按钮,所以直接复制粘贴了。感觉很好,自己以后应该能用到。
iOS中百度地图API的总结
六月 19,2012这篇文章记录了:
引入百度地图API
如何显示地图并定位
如何定位获取经纬度
如何通过定位得到城市,国家,街道等信息
如何通过搜索地理名获得坐标
如何实现公交和驾车路线搜索
如何实现当前位置到指定位置的公交和驾车路线搜索
引入百度地图API
首先,需要到http://dev.baidu.com/wiki/imap/index.php?title=iOS平台/相关下载下载全部内容,包括文档,示例代码和开发包。
然后获取自己的API KEY,具体方法按百度的官网申请就行,比较简单。
下载的文件应该有三个
把inc文件夹拖入到项目中去,引入了头文件,然后如果用真机就把Release-iphoneos里面的.a文件拖拽到项目中去,最后别忘了拖入mapapi.bundle文件,路线节点和图钉的图片来源于素材包。
此外还要引入CoreLocation.framework和QuartzCore.framework,这样引入工作就大功告成,但是要注意一点很重要的,静态库中采用ObjectC++实现,因此需要保证工程中至少有一个.mm后缀的源文件(您可以将任意一个.m后缀的文件改名为.mm),或者在工程属性中指定编译方式,即将XCode的Project-> Edit Active Target -> Build -> GCC4.2 – Language ->Compile Sources As设置为”Objective-C++”。
经过实践,我推荐不这么干,默认是根据文件类型来选择编译的方式,文件要是.m就用Objective-C,要是.mm就是Objective-C++,手动改变会让整个项目都用一种编译方式,很容易出错或者不兼容,比如NavigationItem实例化的时候就会出错,既然百度地图如此特立独行,那么最好的方式就是把地图相关的类改为.mm,其他的依旧,这样只有这个类会用Objective-C++编译方式。
如何显示地图并定位
要让车发动起来先得有引擎,所以在项目的根delegate类里就要通过BMKMapManager这个类来实现地图引擎的启动,具体代码:
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOp
tions:(NSDictionary*)launchOptions {
// 要使用百度地图,请先启动BaiduMapManager
_mapManager = [[BMKMapManageralloc]init];
// 如果要关注网络及授权验证事件,请设定generalDelegate参数
BOOL ret = [_mapManagerstart:@"C5DCEBF3F591FCB69EE0A0B9
B1BB4C948C3FA3CC"generalDelegate:nil]; if (!ret) {
NSLog(@”manager start failed!”);
}
self.window = [[[UIWindow alloc]initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization afterapplication launch.
self.viewController = [[[ViewControlleralloc] initWithNibName:@”ViewController” bundle:nil]autorelease];
self.window.rootViewController =self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
接下来要做的就是添加地图视图,在需要地图的类头文件里添加如下代码(这个类应该是.mm文件):
#import
#import “BMapKit.h”
@interface testViewController :UIViewController//两个协议要引入
{
BMKSearch* _search;//搜索要用到的
BMKMapView* mapView;//地图视图
IBOutlet UITextField* fromeText;
NSString
NSString *cityName;
CLLocationCoordinate2D startPt;
float localLatitude;
float localLongitude;
BOOL localJudge;
NSMutableArray *pathArray;
}
@end
#import “testViewController.h”
#define MYBUNDLE_NAME @ “mapapi.bundle”
#define MYBUNDLE_PATH [[[NSBundlemainBundle] resourcePath] stringByAppendingPathCom
ponent:MYBUNDLE_NAME] #define MYBUNDLE [NSBundle bundleWithPath:MYBUNDLE_PATH]
BOOL isRetina = FALSE;
@interface RouteAnnotation :BMKPointAnnotation
{
int _type; ///<0:起点 1:终点 2:公交 3:地铁4:驾乘
int _degree;
}
@property (nonatomic) int type;
@property (nonatomic) int degree;
@end
@implementation RouteAnnotation
@synthesize type = _type;
@synthesize degree = _degree;
@end
@interface UIImage(InternalMethod)
-(UIImage*)imageRotatedByDegrees:(CGFloat)degrees;
@end
@implementation UIImage(InternalMethod)
-(UIImage*)imageRotatedByDegrees:(CGFloat)degrees
{
CGSize rotatedSize = self.size;
if (isRetina) {
rotatedSize.width *= 2;
rotatedSize.height *= 2;
}
UIGraphicsBeginImageCont
ext(rotatedSize); CGContextRef bitmap =UIGraphicsGetCurrentCont
ext(); CGContextTranslateCTM(bitmap,rotatedSize.width/2, rotatedSize.height/2);
CGContextRotateCTM(bitmap, degrees * M_PI /180);
CGContextRotateCTM(bitmap, M_PI);
CGContextScaleCTM(bitmap, -1.0, 1.0);
CGContextDrawImage(bitmap,CGRectMake(-rotatedSize.width/2, -rotatedSize.height/2,rotatedSize.width, rotatedSize.height), self.CGImage);
UIImage* newImage =UIGraphicsGetImageFromCu
rrentImageContext(); UIGraphicsEndImageContex
t(); return newImage;
}
@end
- (NSString*)getMyBundlePath1:(NSString*)filename
{
NSBundle * libBundle = MYBUNDLE ;
if ( libBundle && filename ){
NSString * s=[[libBundle resourcePath ]stringByAppendingPathCom
ponent : filename]; NSLog ( @”%@” ,s);
return s;
}
return nil ;
}
下面才是真正添加地图的地方:
- (void)viewDidLoad
{
[super viewDidLoad];
mapView = [[BMKMapViewalloc]initWithFrame:CGRectMake(0, 92, 320, 388)];
[self.view addSubview:mapView];
mapView.delegate = self;
[mapViewsetShowsUserLocation:YES];//显示定位的蓝点儿
_search = [[BMKSearchalloc]init];//search类,搜索的时候会用到
_search.delegate = self;
fromeText.text=@”新中关”;
CGSize screenSize = [[UIScreen mainScreen]currentMode].size;
if ((fabs(screenSize.width – 640.0f) <0.1)
&& (fabs(screenSize.height –960.0f) < 0.1))
{
isRetina = TRUE;
}
pathArray=[[NSMutableArray array] retain];
//用来记录路线信息的,以后会用到 }
然后我在ib拖拽了几个按钮,功能显而易见,编译运行就应该成功了
如何定位获取经纬度和
这两个问题一段代码就可以解决,所以归并在一起,当添加了地图引擎和设定setShowsUserLocation:YES以后,地图已经在定位了,通过代理方法可以获得经纬度信息,并通过经纬度信息我可以获得街道城市等信息:
//百度定位获取经纬度信息
-(void)mapView:(BMKMapView *)mapViewdidUpdateUserLocation:(BMKUserLocation *)userLocation{
NSLog(@”!latitude!!!
%f”,userLocation.location.coordinate.latitude);//获取经度 NSLog(@”!longtitude!!!
%f”,userLocation.location.coordinate.longitude);//获取纬度 localLatitude=userLocation.location.coordinate.latitude;//把获取的地理信息记录下来
localLongitude=userLocation.location.coordinate.longitude;
CLGeocoder *Geocoder=[[CLGeocoderalloc]init];//CLGeocoder用法参加之前博客
CLGeocodeCompletionHandl
er handler =^(NSArray *place, NSError *error) { for (CLPlacemark *placemark in place) {
cityStr=placemark.thoroughfare;
cityName=placemark.locality;
NSLog(@”city %@”,cityStr);//获取街道地址
NSLog(@”cityName %@”,cityName);//获取城市名
break;
}
};
CLLocation *loc = [[CLLocation alloc]initWithLatitude:userLocation.location.coordinate.latitudelongitude:userLocation.location.coordinate.longitude];
[Geocoder reverseGeocodeLocation:loccompletionHandler:handler];
}
if (!flag) {
NSLog(@”search failed”);
}
-(void)onGetAddrResult:(BMKAddrInfo*)resulterrorCode:(int)error{
NSLog(@”11111
%f”,result.geoPt.latitude);//获得地理名“新中关”的纬度 NSLog(@”22222
%f”,result.geoPt.longitude);//获得地理名“心中关”的经度 NSLog(@”33333 %@”,result.strAddr);//街道名
NSLog(@”4444%@”,result.addressComponent.province);//所在省份
NSLog(@”555%@”,result.addressComponent.city);
startPt = (CLLocationCoordinate2D){0,0};
startPt =result.geoPt;//把坐标传给startPt保存起来
}
这里可以看到好像百度地图api的结果都不是直接获得的,而是传给对应的代理方法。接下来的路线获取也一样
如何实现公交和驾车路线搜索
当textfield里面默认是新中关的时候,我的驾乘按钮代码如下:
-(IBAction)onClickDriveSearch
{
//清除之前的路线和标记
NSArray* array = [NSArrayarrayWithArray:mapView.annotations];
[mapView removeAnnotations:array];
array = [NSArrayarrayWithArray:mapView.overlays];
[mapView removeOverlays:array];
//清楚路线方案的提示信息
[pathArray removeAllObjects];
//如果是从当前位置为起始点
if (localJudge) {
BMKPlanNode* start = [[BMKPlanNodealloc]init];
startPt.latitude=localLatitude;
startPt.longitude=localLongitude;
start.pt = startPt;
start.name = cityStr;
BMKPlanNode* end = [[BMKPlanNodealloc]init];
end.name = @”三里屯”;
BOOL flag1 = [_searchdrivingSearch:cityName startNode:start endCity:@"北京市"endNode:end];
if (!flag1) {
NSLog(@”search failed”);
}
[start release];
[end release];
}else {
//如果从textfield获取起始点,不定位的话主要看这里
BOOL flag = [_search geocode:fromeText.textwithCity:cityStr];//通过搜索textfield地名获得地名的经纬度,之前已经讲过了,并存储在变量startPt里
if (!flag) {
NSLog(@”search failed”);
}
BMKPlanNode* start = [[BMKPlanNodealloc]init];
start.pt = startPt;//起始点坐标
start.name = fromeText.text;//起始点名字
BMKPlanNode* end = [[BMKPlanNodealloc]init];
end.name = @”三里屯”;//结束点名字
BOOL flag1 = [_searchdrivingSearch:cityName startNode:start endCity:@"北京市"endNode:end];//这个就是驾车路线查询函数,利用了startPt存储的起始点坐标,会调用代理方法onGetDrivingRouteResult
if (!flag1) {
NSLog(@”search failed”);
}
[start release];
[end release];
}
}
//驾车的代理方法
-(void)onGetDrivingRouteResult:(BMKPlanResult*)resulterrorCode:(int)error
{
NSLog(@”onGetDrivingRouteResult:error:%d”,error);
if (error == BMKErrorOk) {
BMKRoutePlan* plan =(BMKRoutePlan*)[result.plans objectAtIndex:0];
RouteAnnotation* item = [[RouteAnnotationalloc]init];
item.coordinate = result.startNode.pt;
item.title = @”起点”;
item.type = 0;
[mapView addAnnotation:item];
[item release];
int index = 0;
int size = [plan.routes count];
for (int i = 0; i < 1; i++) {
BMKRoute* route = [plan.routesobjectAtIndex:i];
for (int j = 0; j < route.pointsCount;j++) {
int len = [route getPointsNum:j];
index += len;
}
}
BMKMapPoint* points = newBMKMapPoint[index];
index = 0;
for (int i = 0; i < 1; i++) {
BMKRoute* route = [plan.routesobjectAtIndex:i];
for (int j = 0; j < route.pointsCount;j++) {
int len = [route getPointsNum:j];
BMKMapPoint* pointArray =(BMKMapPoint*)[route getPoints:j];
memcpy(points + index, pointArray, len *sizeof(BMKMapPoint));
index += len;
}
size = route.steps.count;
for (int j = 0; j < size; j++) {
BMKStep* step = [route.stepsobjectAtIndex:j];
item = [[RouteAnnotation alloc]init];
item.coordinate = step.pt;
item.title = step.content;
item.degree = step.degree * 30;
item.type = 4;
[mapView addAnnotation:item];
[item release];
//把每一个步骤的提示信息存储到pathArray里,以后可以用这个内容实现文字导航
[pathArray addObject:step.content];
}
}
item = [[RouteAnnotation alloc]init];
item.coordinate = result.endNode.pt;
item.type = 1;
item.title = @”终点”;
[mapView addAnnotation:item];
[item release];
BMKPolyline* polyLine = [BMKPolylinepolylineWithPoints:points count:index];
[mapView addOverlay:polyLine];
delete []points;
//打印pathArray,检验获取的文字导航提示信息
for (NSString *string in pathArray) {
NSLog(@”patharray2 %@”,string);
}
}
}
这样驾车的路线就应该可以获取了,编译运行可以看到路线图,同时可以从打印的数组信息得到提示信息,内容就是地图上点击节点弹出的内容
同理,公交按钮的代码:
-(IBAction)onClickBusSearch
{
//清空路线
NSArray* array = [NSArrayarrayWithArray:mapView.annotations];
[mapView removeAnnotations:array];
array = [NSArrayarrayWithArray:mapView.overlays];
[mapView removeOverlays:array];
[pathArray removeAllObjects];
if (localJudge) {
//开始搜索路线,transitSearch调用onGetTransitRouteResult
BMKPlanNode* start = [[BMKPlanNodealloc]init];
startPt.latitude=localLatitude;
startPt.longitude=localLongitude;
start.pt = startPt;
start.name = cityStr;
BMKPlanNode* end = [[BMKPlanNodealloc]init];
end.name = @”三里屯”;
BOOL flag1 = [_searchtransitSearch:cityName startNode:start endNode:end];
if (!flag1) {
NSLog(@”search failed”);
}
[start release];
[end release];
}else{
//由textfield内容搜索,调用onGetAddrResult函数,得到目标点坐标startPt
BOOL flag = [_search geocode:fromeText.textwithCity:cityStr];
if (!flag) {
NSLog(@”search failed”);
}
//开始搜索路线,transitSearch调用onGetTransitRouteResult
BMKPlanNode* start = [[BMKPlanNodealloc]init];
start.pt = startPt;
start.name = fromeText.text;
BMKPlanNode* end = [[BMKPlanNodealloc]init];
end.name = @”三里屯”;
BOOL flag1 = [_searchtransitSearch:cityName startNode:startendNode:end];//公交路线对应的代理方法是onGetTransitRouteResult
if (!flag1) {
NSLog(@”search failed”);
}
[start release];
[end release];
}
}
-(void)onGetTransitRouteResult:(BMKPlanResult*)resulterrorCode:(int)error
{
NSLog(@”onGetTransitRouteResult:error:%d”,error);
if (error == BMKErrorOk) {
BMKTransitRoutePlan* plan =(BMKTransitRoutePlan*)[result.plans objectAtIndex:0];
RouteAnnotation* item = [[RouteAnnotationalloc]init];
item.coordinate = plan.startPt;
item.title = @”起点”;
item.type = 0;
[mapView addAnnotation:item];
[item release];
item = [[RouteAnnotation alloc]init];
item.coordinate = plan.endPt;
item.type = 1;
item.title = @”终点”;
[mapView addAnnotation:item];
[item release];
int size = [plan.lines count];
int index = 0;
for (int i = 0; i < size; i++) {
BMKRoute* route = [plan.routesobjectAtIndex:i];
for (int j = 0; j < route.pointsCount;j++) {
int len = [route getPointsNum:j];
index += len;
}
BMKLine* line = [plan.linesobjectAtIndex:i];
index += line.pointsCount;
if (i == size – 1) {
i++;
route = [plan.routes objectAtIndex:i];
for (int j = 0; j < route.pointsCount;j++) {
int len = [route getPointsNum:j];
index += len;
}
break;
}
}
BMKMapPoint* points = newBMKMapPoint[index];
index = 0;
for (int i = 0; i < size; i++) {
BMKRoute* route = [plan.routesobjectAtIndex:i];
for (int j = 0; j < route.pointsCount;j++) {
int len = [route getPointsNum:j];
BMKMapPoint* pointArray =(BMKMapPoint*)[route getPoints:j];
memcpy(points + index, pointArray, len *sizeof(BMKMapPoint));
index += len;
}
BMKLine* line = [plan.linesobjectAtIndex:i];
memcpy(points + index, line.points,line.pointsCount * sizeof(BMKMapPoint));
index += line.pointsCount;
item = [[RouteAnnotation alloc]init];
item.coordinate =line.getOnStopPoiInfo.pt;
item.title = line.tip;
// NSLog(@”2222
%@”,line.tip);//上车信息,和下车信息加入数组的速度会配合,按顺序加入,不用考虑顺序问题 [pathArray addObject:line.tip];
if (line.type == 0) {
item.type = 2;
} else {
item.type = 3;
}
[mapView addAnnotation:item];
[item release];
route = [plan.routesobjectAtIndex:i+1];
item = [[RouteAnnotation alloc]init];
item.coordinate =line.getOffStopPoiInfo.pt;
item.title = route.tip;
// NSLog(@”2222
%@”,line.tip); // NSLog(@”3333
%@”,item.title);//下车信息 [pathArray addObject:item.title];
if (line.type == 0) {
item.type = 2;
} else {
item.type = 3;
}
[mapView addAnnotation:item];
[item release];
if (i == size – 1) {
i++;
route = [plan.routes objectAtIndex:i];
for (int j = 0; j < route.pointsCount;j++) {
int len = [route getPointsNum:j];
BMKMapPoint* pointArray =(BMKMapPoint*)[route getPoints:j];
memcpy(points + index, pointArray, len *sizeof(BMKMapPoint));
index += len;
}
break;
}
}
BMKPolyline* polyLine = [BMKPolylinepolylineWithPoints:points count:index];
[mapView addOverlay:polyLine];
delete []points;
for (NSString *string in pathArray) {
NSLog(@”bus %@”,string);
}
}
}
目录[隐藏] |
简介
什么是百度地图API?
百度地图移动版API(IOS)是一套基于iOS3.0及以上设备的应用程序接口,通过该接口,您可以轻松访问百度服务和数据,构建功能丰富、交互性强的地图应用程序。百度地图移动版API不仅包含构建地图的基本接口,还提供了诸如地图定位、本地搜索、路线规划等数据服务,你可以根据自己的需要进行选择,目前支持Iphone3.0以上的版本,对iPad暂不支持。
面向的读者
API是提供给那些具有一定iOS编程经验和了解面向对象概念的读者使用。此外,读者还应该对地图产品有一定的了解。
您在使用中遇到任何问题,都可以通过API贴吧或交流群反馈给我们。
获取API Key
用户在使用API之前需要获取百度地图移动版API Key,APIKey可跨平台使用,如果您已经有Android平台的授权Key,可直接在iOS平台使用。该Key与你的百度账户相关联,您必须先有百度帐户,才能获得API KEY。并且,该KEY与您引用API的程序名称有关,具体流程请参照获取密钥。
兼容性
支持iOS3.0及以上系统,百度地图API接口与iOS内置的MapKit包兼容,开发者只需很小的改动即可完成从MapKit到百度地图API的迁移。并且迁移到百度地图API之后很多MapKit中只有iOS4.0以上版本才能使用的特性接口也可以正常使用了。
在您的程序中显示地图
完整的Demo例程可参考相关下载。
引入百度MapAPI的头文件
首先将百度MapAPI提供的头文件和静态库(.a)文件拷贝到您的工程目录下,在XCode中添加新的文件Group,引入百度MapAPI提供的头文件(请使用xcode 4.X以上平台)。
在您需要使用百度MapAPId的文件中添加以下代码
-
#import
"BMapKit.h"
引入静态库文件
百度MapAPI提供了模拟器和真机两中环境所使用的静态库文件,分别存放在libs/Release-iphonesimulator和libs/Release-iphoneos文件夹下。有两种方式可以引入静态库文件:
第一种方式:直接将对应平台的.a文件拖拽至XCode工程左侧的Groups&Files中,缺点是每次在真机和模拟器编译时都需要重新添加.a文件;
第二种方式:使用lipo命令将设备和模拟器的.a合并成一个通用的.a文件,将合并后的通用.a文件拖拽至工程中即可,具体命令如下:
lipo –create Release-iphoneos/libbaidumapapi.a Release-iphonesimulator/libbaidumapapi.a –output libbaidumapapi.a
第三种方式:
1.将API的libs文件夹拷贝到您的Application工程跟目录下
2.在XCode的Project -> Edit Active Target -> Build -> Linking -> Other Linker Flags中添加-lbaidumapapi
3.设置静态库的链接路径,在XCode的Project -> Edit Active Target -> Build -> Search Path -> Library Search Paths中添加您的静态库目录,比如"$(SRCROOT)/../libs/Release$(EFFECTIVE_PLATFORM_NAME)",$(SRCROOT)宏代表您的工程文件目录,$(EFFECTIVE_PLATFORM_NAME)宏代表当前配置是OS还是simulator
注:静态库中采用ObjectC++实现,因此需要您保证您工程中至少有一个.mm后缀的源文件(您可以将任意一个.m后缀的文件改名为.mm),或者在工程属性中指定编译方式,即将XCode的Project -> Edit Active Target -> Build -> GCC4.2 - Language -> Compile Sources As设置为"Objective-C++"
引入CoreLocation.framework和QuartzCore.framework
百度MapAPI中提供了定位功能和动画效果,因此您需要在您的XCode工程中引入CoreLocation.framework和QuartzCore.framework。 添加方式:右键点击Xcode工程左侧的Frameworks文件夹,add->Existing Frameworks,在弹出窗口中选中这两个framework,点击add即可。
引入mapapi.bundle资源文件
该步骤为可选,mapapi.bundle中存储了定位、默认大头针标注View及路线关键点的资源图片。如果您不需要使用内置的图片显示功能,则可以不添加此bundle文件。您也可以根据具体需求任意替换或删除该bundle中的图片文件。
添加方式:将mapapi.bundle拷贝到您的工程目录,直接将该bundle文件托拽至XCode工程左侧的Groups&Files中即可。
初始化BMKMapManager
在您的AppDelegate.h文件中添加BMKMapManager的定义
-
@
interface BaiduMapApiDemoAppDelegate
: NSObject
<UIApplicationDelegate
>
{
-
UIWindow
*window
;
-
UINavigationController
*navigationController
;
-
-
BMKMapManager
* _mapManager
;
-
}
在您的AppDelegate.m文件中添加对BMKMapManager的初始化,并填入您申请的授权Key,示例如下
-
-
(BOOL
)application
:
(UIApplication
*
)application didFinishLaunchingWithOptions
:
(NSDictionary
*
)launchOptions
{
-
// 要使用百度地图,请先启动BaiduMapManager
-
_mapManager
=
[
[BMKMapManager alloc
]init
]
;
-
// 如果要关注网络及授权验证事件,请设定generalDelegate参数
-
BOOL ret
=
[_mapManager start
:@
"在此处输入您的授权Key" generalDelegate
:nil
]
;
-
if
(
!ret
)
{
-
NSLog
(@
"manager start failed!"
)
;
-
}
-
// Add the navigation controller's view to the window and display.
-
[self.
window addSubview
:navigationController.
view
]
;
-
[self.
window makeKeyAndVisible
]
;
-
return YES
;
-
}
创建BMKMapView
在您的ViewController.m文件中添加BMKMapView的创建代码,示例如下
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
BMKMapView
* mapView
=
[
[BMKMapView alloc
]initWithFrame
:CGRectMake
(
0,
0,
320,
480
)
]
;
-
self.
view
= mapView
;
-
}
编译,运行,效果如下图所示:
默认地图已经可以支持多点触摸,双击放大,多点单击缩小等操作,并都附带动画效果。
注意事项
1.静态库中采用ObjectC++实现,因此需要您保证您工程中至少有一个.mm后缀的源文件(您可以将任意一个.m后缀的文件改名为.mm),或者在工程属性中指定编译方式,即将XCode的Project -> Edit Active Target -> Build -> GCC4.2 - Language -> Compile Sources As设置为"Objective-C++"
2.如果您只在Xib文件中使用了BMKMapView,没有在代码中使用BMKMapView,编译器在链接时不会链接对应符合,需要在工程属性中显式设定:在XCode的Project -> Edit Active Target -> Build -> Linking -> Other Linker Flags中添加-all_load
3.授权Key的申请:授权Key可跨平台使用,如果您已经申请过Android的key,可直接在iOS中使用;如果还没有授权Key,请到http://dev.baidu.com/wiki/static/imap/key/ 页面申请
卫星图图层
-
[mapView setMapType
:BMKMapTypeSatellite
]
;
运行后效果如下:
实时路况图层
目前支持以下11个城市的实时路况信息:北京,上海,广州,深圳,南京,南昌,成都,重庆,武汉,大连,常州。在地图中通过以下代码设置显示实时路况图层:
打开实时路况图层:
-
[mapView setMapType
:BMKMapTypeTrafficOn
]
;
关闭实时路况图层:
-
[mapView setMapType
:BMKMapTypeTrafficOff
]
;
运行后效果如下:
地图覆盖物
覆盖物概述
地图上自定义的标注点和覆盖物我们统称为地图覆盖物。您可以通过定制BMKAnnotation和BMKOverlay来添加对应的标注点和覆盖物。地图覆盖物的设计遵循数据与View分离的原则,BMKAnnotation和BMKOverlay系列的类主要用来存放覆盖物相关的数据,BMKAnnotaionView和BMKOverlayView系列类为覆盖物对应的View。
添加标注
BMKAnnotation为标注对应的protocal,您可以自定义标注类实现该protocal。百度地图API也预置了基本的标注点:BMKPointAnnotation,和一个大头针标注View:BMKPinAnnotationView,您可以直接使用来显示标注。示例如下:
修改您的ViewController.h文件,添加以下代码,使您的ViewController实现BMKMapViewDelegate协议:
-
#import
<UIKit
/UIKit.
h
>
-
#import
"BMapKit.h"
-
@
interface AnnotationDemoViewController
: UIViewController
<BMKMapViewDelegate
>
{
-
IBOutlet BMKMapView
* mapView
;
-
}
-
@end
修改您的ViewController.m文件,实现BMKMapViewDelegate的mapView:viewForAnnotation:函数,并在viewDidLoad添加标注数据对象
-
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
-
// 设置mapView的Delegate
-
mapView.
delegate
= self
;
-
-
// 添加一个PointAnnotation
-
BMKPointAnnotation
* annotation
=
[
[BMKPointAnnotation alloc
]init
]
;
-
CLLocationCoordinate2D coor
;
-
coor.
latitude
=
39.915
;
-
coor.
longitude
=
116.404
;
-
annotation.
coordinate
= coor
;
-
annotation.
title
= @
"这里是北京"
;
-
[mapView addAnnotation
:annotation
]
;
-
}
-
-
// Override
-
-
(BMKAnnotationView
*
)mapView
:
(BMKMapView
*
)mapView viewForAnnotation
:
(id
<BMKAnnotation
>
)annotation
-
{
-
if
(
[annotation isKindOfClass
:
[BMKPointAnnotation
class
]
]
)
{
-
BMKPinAnnotationView
*newAnnotationView
=
[
[BMKPinAnnotationView alloc
] initWithAnnotation
:annotation reuseIdentifier
:@
"myAnnotation"
]
;
-
newAnnotationView.
pinColor
= BMKPinAnnotationColorPurple
;
-
newAnnotationView.
animatesDrop
= YES
;
// 设置该标注点动画显示
-
return newAnnotationView
;
-
}
-
return nil
;
-
}
运行后,会在地图显示对应的标注点,点击会弹出气泡,效果如图:
删除标注
通过removeAnnotation:函数实现对已添加标注的删除功能,示例如下:
-
if
(annotation
!= nil
)
{
-
[mapView removeAnnotation
:annotation
]
;
-
}
添加折线
修改您的ViewController.h文件,添加以下代码,使您的ViewController实现BMKMapViewDelegate协议:
-
#import
<UIKit
/UIKit.
h
>
-
#import
"BMapKit.h"
-
@
interface OverlayDemoViewController
: UIViewController
<BMKMapViewDelegate
>
{
-
IBOutlet BMKMapView
* mapView
;
-
}
-
@end
修改您的ViewController.m文件,实现BMKMapViewDelegate的mapView:viewForOverlay:函数,并在viewDidLoad添加折线数据对象:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
-
// 设置delegate
-
mapView.
delegate
= self
;
-
-
// 添加折线覆盖物
-
CLLocationCoordinate2D coors
[
2
]
=
{
0
}
;
-
coors
[
0
].
latitude
=
39.315
;
-
coors
[
0
].
longitude
=
116.304
;
-
coors
[
1
].
latitude
=
39.515
;
-
coors
[
1
].
longitude
=
116.504
;
-
BMKPolyline
* polyline
=
[BMKPolyline polylineWithCoordinates
:coors count
:
2
]
;
-
[mapView addOverlay
:polyline
]
;
-
}
-
-
// Override
-
-
(BMKOverlayView
*
)mapView
:
(BMKMapView
*
)mapView viewForOverlay
:
(id
<BMKOverlay
>
)overlay
{
-
if
(
[overlay isKindOfClass
:
[BMKPolyline
class
]
]
)
{
-
BMKPolylineView
* polylineView
=
[
[
[BMKPolylineView alloc
] initWithOverlay
:overlay
] autorelease
]
;
-
polylineView.
strokeColor
=
[
[UIColor purpleColor
] colorWithAlphaComponent
:
1
]
;
-
polylineView.
lineWidth
=
5.0
;
-
return polylineView
;
-
}
-
return nil
;
-
}
运行后,效果如图:
添加多边形
修改您的ViewController.h文件,添加以下代码,使您的ViewController实现BMKMapViewDelegate协议:
修改您的ViewController.m文件,实现BMKMapViewDelegate的mapView:viewForOverlay:函数,并在viewDidLoad添加多边形数据对象:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
-
// 设置delegate
-
mapView.
delegate
= self
;
-
-
// 添加多边形覆盖物
-
CLLocationCoordinate2D coords
[
3
]
=
{
0
}
;
-
coords
[
0
].
latitude
=
39
;
-
coords
[
0
].
longitude
=
116
;
-
coords
[
1
].
latitude
=
38
;
-
coords
[
1
].
longitude
=
115
;
-
coords
[
2
].
latitude
=
38
;
-
coords
[
2
].
longitude
=
117
;
-
BMKPolygon
* polygon
=
[BMKPolygon polygonWithCoordinates
:coords count
:
3
]
;
-
[mapView addOverlay
:polygon
]
;
-
}
-
-
// Override
-
-
(BMKOverlayView
*
)mapView
:
(BMKMapView
*
)mapView viewForOverlay
:
(id
<BMKOverlay
>
)overlay
{
-
if
(
[overlay isKindOfClass
:
[BMKPolygon
class
]
]
)
{
-
BMKPolygonView
* polygonView
=
[
[
[BMKPolygonView alloc
] initWithOverlay
:overlay
] autorelease
]
;
-
polygonView.
strokeColor
=
[
[UIColor purpleColor
] colorWithAlphaComponent
:
1
]
;
-
polygonView.
fillColor
=
[
[UIColor cyanColor
] colorWithAlphaComponent
:
0.2
]
;
-
polygonView.
lineWidth
=
5.0
;
-
return polygonView
;
-
}
-
return nil
;
-
}
运行后,效果如图:
添加圆
修改您的ViewController.h文件,添加以下代码,使您的ViewController实现BMKMapViewDelegate协议:
修改您的ViewController.m文件,实现BMKMapViewDelegate的mapView:viewForOverlay:函数,并在viewDidLoad添加园数据对象:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
-
// 设置delegate
-
mapView.
delegate
= self
;
-
-
// 添加圆形覆盖物
-
CLLocationCoordinate2D coor
;
-
coor.
latitude
=
39.915
;
-
coor.
longitude
=
116.404
;
-
BMKCircle
* circle
=
[BMKCircle circleWithCenterCoordinate
:coor radius
:
5000
]
;
-
[mapView addOverlay
:circle
]
;
-
}
-
-
// Override
-
-
(BMKOverlayView
*
)mapView
:
(BMKMapView
*
)mapView viewForOverlay
:
(id
<BMKOverlay
>
)overlay
{
-
if
(
[overlay isKindOfClass
:
[BMKCircle
class
]
]
)
{
-
BMKCircleView
* circleView
=
[
[
[BMKCircleView alloc
] initWithOverlay
:overlay
] autorelease
]
;
-
circleView.
fillColor
=
[
[UIColor cyanColor
] colorWithAlphaComponent
:
0.5
]
;
-
circleView.
strokeColor
=
[
[UIColor blueColor
] colorWithAlphaComponent
:
0.5
]
;
-
circleView.
lineWidth
=
10.0
;
-
return circleView
;
-
}
-
return nil
;
-
}
运行后,效果如图:
删除Overlay
通过removeOverlay:函数实现对已添加标注的删除功能,示例如下:
-
if
(overlay
!= nil
)
{
-
[mapView removeOverlay
:overlay
]
;
-
}
服务类
百度地图API提供的搜索服务包括:POI检索,多关键字检索,公交方案检索,驾车路线检索,步行路线检索,地理编码,反地理编码。
所有检索请求接口均为异步接口,您必须实现BMKSearchDelegate协议,在检索到结果后,API会回调BMKSearchDelegate对应的接口,通知调用者检索结果数据。
BMKSearchDelegate对应的接口如下:
-
/**
-
*返回POI搜索结果
-
*@param poiResultList 搜索结果列表,成员类型为BMKPoiResult
-
*@param type 返回结果类型: BMKTypePoiList,BMKTypeAreaPoiList,BMKAreaMultiPoiList
-
*@param error 错误号,@see BMKErrorCode
-
*/
-
-
(
void
)onGetPoiResult
:
(NSArray
*
)poiResultList searchType
:
(
int
)type errorCode
:
(
int
)error
{
-
}
-
/**
-
*返回公交搜索结果
-
*@param result 搜索结果
-
*@param error 错误号,@see BMKErrorCode
-
*/
-
-
(
void
)onGetTransitRouteResult
:
(BMKPlanResult
*
)result errorCode
:
(
int
)error
{
-
}
-
-
/**
-
*返回驾乘搜索结果
-
*@param result 搜索结果
-
*@param error 错误号,@see BMKErrorCode
-
*/
-
-
(
void
)onGetDrivingRouteResult
:
(BMKPlanResult
*
)result errorCode
:
(
int
)error
{
-
}
-
/**
-
*返回步行搜索结果
-
*@param result 搜索结果
-
*@param error 错误号,@see BMKErrorCode
-
*/
-
-
(
void
)onGetWalkingRouteResult
:
(BMKPlanResult
*
)result errorCode
:
(
int
)error
{
-
}
-
/**
-
*返回地址信息搜索结果
-
*@param result 搜索结果
-
*@param error 错误号,@see BMKErrorCode
-
*/
-
-
(
void
)onGetAddrResult
:
(BMKAddrInfo
*
)result errorCode
:
(
int
)error
{
-
}
-
/**
-
*返回公交详情搜索结果
-
*@param result 搜索结果
-
*@param error 错误号,@see BMKErrorCode
-
*/
-
-
(
void
)onGetBusDetailResult
:
(BMKBusLineResult
*
)busLineResult errorCode
:
(
int
)error
{
-
}
POI检索
百度地图API提供以下几类POI检索类型:城市内检索,周边检索,范围检索,多关键字检索。
此处以城市内检索为例说明:
在ViewController.h中声明BMKSearch对象,并将ViewController实现BMKSearchDelegate协议,代码如下:
-
@
interface PoiSearchDemoViewController
: UIViewController
<BMKMapViewDelegate, BMKSearchDelegate
>
{
-
IBOutlet BMKMapView
* _mapView
;
-
BMKSearch
* _search
;
-
}
在ViewController.m的viewDidLoad中创建BMKSearch对象,设置对应的delegate,并实现BMKSearchDelegate协议中获取POI结果的方法,代码如下:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
_mapView.
delegate
= self
;
-
_search
=
[
[BMKSearch alloc
]init
]
;
-
_search.
delegate
= self
;
-
//发起POI检索
-
[_search poiSearchInCity
:@
"北京" withKey
:@
"西单" pageIndex
:
0
]
;
-
}
-
-
(
void
)onGetPoiResult
:
(NSArray
*
)poiResultList searchType
:
(
int
)type errorCode
:
(
int
)error
-
{
-
if
(error
== BMKErrorOk
)
{
-
BMKPoiResult
* result
=
[poiResultList objectAtIndex
:
0
]
;
-
for
(
int i
=
0
; i
< result.
poiInfoList.
count
; i
++
)
{
-
BMKPoiInfo
* poi
=
[result.
poiInfoList objectAtIndex
:i
]
;
-
BMKPointAnnotation
* item
=
[
[BMKPointAnnotation alloc
]init
]
;
-
item.
coordinate
= poi.
pt
;
-
item.
title
= poi.
name
;
-
[_mapView addAnnotation
:item
]
;
-
[item release
]
;
-
}
-
}
-
}
运行效果如图:
示例代码请参考相关下载demo工程中的PoiSearchDemoViewController.mm文件
公交方案检索
在ViewController.h中声明BMKSearch对象,并将ViewController实现BMKSearchDelegate协议,代码参考 POI检索中的示例代码.
在ViewController.m中创建BMKSearch对象,设置对应的delegate,并实现BMKSearchDelegate协议中获取公交路线结果的方法,代码如下:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
_mapView.
delegate
= self
;
-
_search
=
[
[BMKSearch alloc
]init
]
;
-
_search.
delegate
= self
;
-
//发起公交检索
-
BMKPlanNode
* start
=
[
[BMKPlanNode alloc
]init
]
;
-
start.
name
= @
"天安门"
;
-
BMKPlanNode
* end
=
[
[BMKPlanNode alloc
]init
]
;
-
end.
name
= @
"百度大厦"
;
-
[_search transitSearch
:@
"北京" startNode
:start endNode
:end
]
;
-
[start release
]
;
-
[end release
]
;
-
}
-
-
(
void
)onGetTransitRouteResult
:
(BMKPlanResult
*
)result errorCode
:
(
int
)error
-
{
-
// 在此处添加您对公交方案结果的处理
-
}
将公交方案对应的路线和关键点绘制在地图上,效果如下图:
示例代码请参考相关下载demo工程中的RouteSearchDemoViewController.mm文件
驾车路线检索
在ViewController.h中声明BMKSearch对象,并将ViewController实现BMKSearchDelegate协议,代码参考 POI检索中的示例代码.
在ViewController.m中创建BMKSearch对象,设置对应的delegate,并实现BMKSearchDelegate协议中获取驾车路线结果的方法,代码如下:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
_mapView.
delegate
= self
;
-
_search
=
[
[BMKSearch alloc
]init
]
;
-
_search.
delegate
= self
;
-
//发起公交检索
-
BMKPlanNode
* start
=
[
[BMKPlanNode alloc
]init
]
;
-
start.
name
= @
"天安门"
;
-
BMKPlanNode
* end
=
[
[BMKPlanNode alloc
]init
]
;
-
end.
name
= @
"百度大厦"
;
-
[_search drivingSearch
:@
"北京" startNode
:start endCity
:@
"北京" endNode
:end
]
;
-
[start release
]
;
-
[end release
]
;
-
}
-
-
(
void
)onGetDrivingRouteResult
:
(BMKPlanResult
*
)result errorCode
:
(
int
)error
-
{
-
// 在此处添加您对驾车方案结果的处理
-
}
将驾车方案对应的路线和关键点绘制在地图上,效果如下图:
示例代码请参考相关下载demo工程中的RouteSearchDemoViewController.mm文件
步行路线检索
在ViewController.h中声明BMKSearch对象,并将ViewController实现BMKSearchDelegate协议,代码参考 POI检索中的示例代码.
在ViewController.m中创建BMKSearch对象,设置对应的delegate,并实现BMKSearchDelegate协议中获取步行路线结果的方法,代码如下:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
_mapView.
delegate
= self
;
-
_search
=
[
[BMKSearch alloc
]init
]
;
-
_search.
delegate
= self
;
-
//发起步行检索
-
BMKPlanNode
* start
=
[
[BMKPlanNode alloc
]init
]
;
-
start.
name
= @
"天安门"
;
-
BMKPlanNode
* end
=
[
[BMKPlanNode alloc
]init
]
;
-
end.
name
= @
"百度大厦"
;
-
[_search walkingSearch
:@
"北京" startNode
:start endCity
:@
"北京" endNode
:end
]
;
-
[start release
]
;
-
[end release
]
;
-
}
-
-
(
void
)onGetWalkingRouteResult
:
(BMKPlanResult
*
)result errorCode
:
(
int
)error
-
{
-
// 在此处添加您对步行方案结果的处理
-
}
将步行方案对应的路线和关键点绘制在地图上,效果如下图:
示例代码请参考相关下载demo工程中的RouteSearchDemoViewController.mm文件
地理编码
在ViewController.h中声明BMKSearch对象,并将ViewController实现BMKSearchDelegate协议,代码参考 POI检索中的示例代码.
在ViewController.m中创建BMKSearch对象,设置对应的delegate,并实现BMKSearchDelegate协议中获取地理编码结果的方法,代码如下:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
_mapView.
delegate
= self
;
-
_search
=
[
[BMKSearch alloc
]init
]
;
-
_search.
delegate
= self
;
-
//发起地理编码
-
[_search geocode
:@
"东长安街33号" withCity
:@
"北京"
]
;
-
}
-
-
(
void
)onGetAddrResult
:
(BMKAddrInfo
*
)result errorCode
:
(
int
)error
-
{
-
// 在此处添加您对地理编码结果的处理
-
}
完整的示例代码请参考相关下载demo工程中的GeocodeDemoViewController.mm文件
反地理编码
在ViewController.h中声明BMKSearch对象,并将ViewController实现BMKSearchDelegate协议,代码参考 POI检索中的示例代码.
在ViewController.m中创建BMKSearch对象,设置对应的delegate,并实现BMKSearchDelegate协议中获取反地理编码结果的方法,代码如下:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
_mapView.
delegate
= self
;
-
_search
=
[
[BMKSearch alloc
]init
]
;
-
_search.
delegate
= self
;
-
//发起反地理编码
-
CLLocationCoordinate2D pt
=
(CLLocationCoordinate2D
)
{
39.915101,
116.403981
}
;
-
[_search reverseGeocode
:pt
]
;
-
}
-
-
(
void
)onGetAddrResult
:
(BMKAddrInfo
*
)result errorCode
:
(
int
)error
-
{
-
// 在此处添加您对反地理编码结果的处理
-
}
完整的示例代码请参考相关下载demo工程中的GeocodeDemoViewController.mm文件
公交详情检索
在ViewController.h中声明BMKSearch对象,并将ViewController实现BMKSearchDelegate协议,代码参考 POI检索中的示例代码.
在ViewController.m中创建BMKSearch对象,设置对应的delegate,并实现BMKSearchDelegate协议中获取驾车路线结果的方法。发起公交详情搜索前,先进行POI检索,检索结果中poi.epoitype == 2时表示该类型为公交线路,才可发起公交搜索,代码如下:
-
-
(
void
)viewDidLoad
{
-
[
super viewDidLoad
]
;
-
_mapView.
delegate
= self
;
-
_search
=
[
[BMKSearch alloc
]init
]
;
-
_search.
delegate
= self
;
-
//发起poi检索
-
[_search poiSearchInCity
:@
"北京" withKey
:@
"717" pageIndex
:
0
]
;
-
}
-
-
(
void
)onGetPoiResult
:
(NSArray
*
)poiResultList searchType
:
(
int
)type errorCode
:
(
int
)error
-
{
-
if
(error
== BMKErrorOk
)
{
-
BMKPoiResult
* result
=
[poiResultList objectAtIndex
:
0
]
;
-
for
(
int i
=
0
; i
< result.
poiInfoList.
count
; i
++
)
{
-
BMKPoiInfo
* poi
=
[result.
poiInfoList objectAtIndex
:i
]
;
-
if
(poi.
epoitype
==
2
)
-
{
-
break
;
-
}
-
}
-
// 发起公交详情搜索
-
if
(poi
!= nil
&& poi.
epoitype
==
2
)
-
{
-
NSLog
(poi.
uid
)
;
-
BOOL flag
=
[_search busLineSearch
:@
"北京" withKey
:poi.
uid
]
;
-
if
(
!flag
)
{
-
NSLog
(@
"search failed!"
)
;
-
}
-
}
-
}
-
}
-
-
(
void
)onGetBusDetailResult
:
(BMKBusLineResult
*
)busLineResult errorCode
:
(
int
)error
-
{
-
// 在此处添加您对公交详情结果的处理
-
}
将公交详情对应的路线和关键点绘制在地图上,效果如下图:
示例代码请参考相关下载demo工程中的BusLineSearchViewController.mm文件
定位
您可以通过以下代码来开启定位功能:
-
[mapView setShowsUserLocation
:YES
]
;
定位成功后,可以通过mapView.userLocation来获取位置数据。
完整的示例代码请参考相关下载demo工程中的LocationDemoViewController.mm文件
离线地图
SDK v1.1以后支持离线地图导入,从官网下载对应的离线包,通过itunes导入对应程序的共享目录,对于越狱的手机可以通过91助手拷到对应程序目录下的document目录:
-
_offlineMap
=
[
[BMKOfflineMap alloc
]init
]
;
-
_offlineMap.
delegate
= self
;
完整的示例代码请参考相关下载demo工程中的OfflineDemoViewController.m文件