高德地图是一款经常在苹果手机使用的地图平台。在国内iOS的地图服务都是由高德提供的。在上一节中,我们介绍了一下如何使用MapKit框架实现地图服务,以及如何调用了系统内置的地图应用。除了使用iOS系统的自带框架之外,高德地图也为我们提供了一套SDK来实现地图服务和定位功能,下面我们就来看一下高德地图的SDK的使用以及高德地图的项目开发。
高德地图SDK是一套基于iOS6.0.0及以上版本的地图应用程序开发接口,供开发者在自己的iOS应用中加入地图相关的功能。通过高德地图SDK,开发者可以轻松地开发出地图显示与操作、兴趣点搜索、地理编码、路线规划等功能。高德地图自2.4.0版本起,适配了armv7、armv7s、arm64 架构。iOS 3D地图V3.0.0起,进入全矢量时代,3D矢量地图地图渲染效果大幅提升;高德地图SDK支持多实例特性,在同一页面创建多个地图对象,相互操作不会收到干扰;同时,白天新增蓝天白云效果,夜晚增加星空效果;底图上的POI触摸及显示信息比之前更为精准和直观。
好了,不多说,我们下面介绍一下高德地图开放平台为我们提供了哪些支持。
高德地图iOS SDK是一套基于 iOS 6.0.0 及以上版本的地图应用程序开发接口,适配armv7、arm64架构,适配iOS9,开启Bitcode。
注册流程就不多做介绍了,按照高德地图开发平台的要求一次操作就好了。
用户在使用 SDK 时需获取高德地图API Key,不同工程对应不同的Bundle identifer(即安全码),要申请不同Key。
第一步:访问 http://lbs.amap.com/dev/key/,使用高德开发者账号登陆(若不是开发者账号,则会提醒认证成为开发者)。
第二步:在“应用与权限”页面点击上方的“创建新应用”按钮,依次:输入应用名名称,和应用类型创建应用。
第三步:点击“添加新Key”按钮,填入key的名称,选择绑定的服务为“iOS平台SDK”,输入安全码:Bundle Identifier,如下图所示:在当前页面的“Key”列表中中可以看到所申请的Key,如下图所示:
第一步:引入地图库
将解压后的MAMapKit.framework 文件copy或拖拽到工程文件夹中,左侧目录选中工程名,在 TARGETS->Build Phases-> Link Binary With Libaries 中点击“+”按钮,在弹出的窗口中点击“Add Other”按钮,选择工程目录下的 MAMapKit.framework 文件添加到工程中。
注意:
1. 若还需使用搜索库,则用同样的方法,将解压后的 AMapSearchKit.framework 文件添加到工程中。
2. Xcode7之后,可直接将库文件拖到工程中,完成此操作。
第二步:引入AMap.bundle资源文件
AMap.bundle资源文件中存储了定位、默认大头针标注视图等图片,可利用这些资源图片进行开发。
左侧目录中选中工程名,在右键菜单中选择Add Files to “工程名”…,从MAMapKit.framework->Resources文件中选择AMap.bundle文件,并勾选“Copy items if needed”复选框,单击“Add”按钮,将资源文件添加到工程中。
注意:2D地图和3D地图的资源文件是不同的,在进行SDK切换时,需要同时更换对应的资源文件。
第三步:引入系统库
需引入的系统库如下表所示:
1. | UIKit.framework | 2D、3D、Search |
---|---|---|
2. | Foundation.framework | 2D、3D、Search |
3. | CoreGraphics.framework | 2D、3D、Search |
4. | QuartzCore.framework | 2D、3D |
5. | OpenGLES.framework | 3D |
6. | CoreLocation.framework | 2D、3D |
7. | CoreTelephony.framework | 2D、3D、Search |
8. | SystemConfiguration.framework | 2D、3D、Search |
9. | libz.dylib 或 libz.tbd | 2D、3D、Search |
10. | libstdc++6.0.9.dylib 或 libstdc++6.0.9.tbd | 2D、3D、Search说明:Search V3.0.0及以上版本不需要引入。 |
11. | libc++.dylib 或 libc++.tbd | 2D(V3.3.0及以上)、3D(V3.0.0及以上) |
12. | Security.framework | 2D、3D |
说明:
引入系统库的操作如下:左侧目录中选中工程名,在TARGETS->Build Settings-> Link Binary With Libaries中点击“+”按钮,在弹出的窗口中查找并选择所需的库(见下表),单击“Add”按钮,将库文件添加到工程中。
第四步:环境配置;
在TARGETS->Build Settings->Other Linker Flags 中添加-ObjC,C大写。
注意:V2.3.0(含)之前版本不支持arm64,需在 TARGETS->Build Settings->Architectures 点出选择框,选择 “Other”,将默认值修改为 $(ARCHS_STANDARD_32_BIT)。
为保证SDK的功能在iOS 9中正常使用,需在“Info.plist”中做如下配置,
利用地图SDK提供的接口,开发者可免费使用高德的地图数据。我们提供的地图SDK有两种:3D矢量地图和2D栅格地图,其中:3D矢量地图的效果炫,用户可自定义的程度高;2D栅格地图包体积小,提供英文地图。还具备以下优秀特质:
多样的手势操作。支持双指缩放、双击放大、旋转等手势操作,并且有相应的接口来控制手势操作。
本文主要以2D栅格地图为例,介绍高德地图SDK的使用。
示例代码:
#import "ViewController.h"
#import
@interface ViewController ()<MAMapViewDelegate>
{
MAMapView *_mapView;// 地图视图
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 配置用户APP Key
[[MAMapServices sharedServices] setApiKey:@"f0157e7110c99b150d81bd71c7e37c67"];
// 初始化地图控件
_mapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
// 设置代理
_mapView.delegate = self;
[self.view addSubview:_mapView];
}
@end
3D矢量地图SDK提供三种地图类型:
1)普通地图 MAMapTypeStandard;
2)卫星地图 MAMapTypeSatellite;
3)夜间地图 MAMapTypeStandardNight;
2D栅格地图SDK提供两种地图类型:
1)普通地图 MAMapTypeStandard
2)卫星地图 MAMapTypeSatellite。
地图类型切换只需设置相应类型,地图默认显示标准地图,从标准地图切换成卫星地图的方法如下:
_mapView.mapType = MAMapTypeSatellite;
高德地图 iOS SDK提供北京,上海,广州,深圳,武汉,沈阳,南京,宁波,重庆,杭州,青岛,成都,天津,大连,无锡,西安,石家庄,太原,常州,厦门,长春,福州,珠海,东莞,长沙,苏州,金华,佛山,济南,泉州,西宁,乌鲁木齐,嘉兴,香港,鄂尔多斯,南通,中山,惠州,镇江,郑州,合肥,昆明,德州,朝阳,抚顺,大同,荆州,温州,台州,绍兴,莆田,南平,漳州,宁德,三明,龙岩,烟台,阳江,江门,保定,临沂61个城市及城际间的实时交通路况。
显示实时交通路况的代码如下:
_mapView.showTraffic= YES;
标注Annotation,就是地图标注注释,目前提供两种标注:
地图上用“大头针”显示一个带有标题的位置点,大头针展示效果是MAPinAnnotationView,点击大头针弹出气泡,气泡内写着“**”,气泡内信息存储在MAPointAnnotation,在地图上添加一个标注的步骤如下:
1. 定义一个 MAPointAnnotation 对象,添加数据;
2. 使用 MAMapView 的 addAnnotation: 方法添加到地图;
3. 实现 mapView:viewForAnnotation: 代理方法;
4. 在代理内定义 MAPinAnnotationView 对象。
我们先来看一下大头针标注的实现。iOS SDK提供的大头针标注MAPinAnnotationView,通过它可以设置大头针颜色、是否显示动画、是否支持长按后拖拽大头针改变坐标等。在地图上添加大头针标注的步骤如下:
示例代码:
#import "ViewController.h"
#import
@interface ViewController ()<MAMapViewDelegate>
{
MAMapView *_mapView;// 地图视图
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 配置用户APP Key
[[MAMapServices sharedServices] setApiKey:@"f0157e7110c99b150d81bd71c7e37c67"];
// 初始化地图控件
_mapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
// 设置代理
_mapView.delegate = self;
// 设置地图类型
_mapView.mapType = MAMapTypeSatellite;// 卫星地图
// 显示实时交通
_mapView.showTraffic = YES;
[self.view addSubview:_mapView];
// 添加大头针标记
MAPointAnnotation *pointAnnotation = [[MAPointAnnotation alloc] init];
pointAnnotation.coordinate = CLLocationCoordinate2DMake(39.989631, 116.481018);
pointAnnotation.title = @"我的位置";
pointAnnotation.subtitle = @"北京帝都";
[_mapView addAnnotation:pointAnnotation];
}
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id )annotation
{
if ([annotation isKindOfClass:[MAPointAnnotation class]])
{
static NSString *pointReuseIndentifier = @"pointReuseIndentifier";
MAPinAnnotationView*annotationView = (MAPinAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
if (annotationView == nil)
{
annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
}
annotationView.canShowCallout= YES; //设置气泡可以弹出,默认为NO
annotationView.animatesDrop = YES; //设置标注动画显示,默认为NO
annotationView.draggable = YES; //设置标注可以拖动,默认为NO
annotationView.pinColor = MAPinAnnotationColorPurple;
return annotationView;
}
return nil;
}
@end
高德地图iOS SDK可自定义标注(包括 自定义标注图标 和 自定义气泡图标),均通过MAAnnotationView来实现。若大头针样式的标注不能满足您的需求,您可以自定义标注图标。步骤如下:
示例代码:
// 自定义标注视图
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id)annotation
{
if ([annotation isKindOfClass:[MAPointAnnotation class]])
{
static NSString *reuseIndetifier = @"annotationReuseIndetifier";
MAAnnotationView *annotationView = (MAAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
if (annotationView == nil)
{
annotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:reuseIndetifier];
}
annotationView.image = [UIImage imageNamed:@"category_3"];
//设置中心点偏移,使得标注底部中间点成为经纬度对应点
annotationView.centerOffset = CGPointMake(0, -18);
return annotationView;
}
return nil;
}
运行效果有一个问题,点击位置弹出气泡并不出现。
气泡在iOS中又称为callout,它由背景和气泡内容构成,每个气泡显示的内容是根据您的需求定义的,这里我们按照如上图所示的气泡介绍实现一个自定义气泡的步骤:
示例代码:
CustomCalloutView.h
#import
@interface CustomCalloutView : UIView
@property (nonatomic, strong) UIImage *image; // 标记图
@property (nonatomic, copy) NSString *title; // 标题
@property (nonatomic, copy) NSString *subtitle; // 子标题
@property (nonatomic, strong) UIImageView *portraitView;
@property (nonatomic, strong) UILabel *subtitleLabel;
@property (nonatomic, strong) UILabel *titleLabel;
@end
CustomCalloutView.m
#import "CustomCalloutView.h"
#define kPortraitMargin 5
#define kPortraitWidth 70
#define kPortraitHeight 50
#define kTitleWidth 120
#define kTitleHeight 20
@implementation CustomCalloutView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = [UIColor clearColor];
[self initSubViews];
}
return self;
}
- (void)initSubViews {
// 添加图片,即商户图
self.portraitView = [[UIImageView alloc] initWithFrame:CGRectMake(kPortraitMargin, kPortraitMargin, kPortraitWidth, kPortraitHeight)];
self.portraitView.backgroundColor = [UIColor blackColor];
[self addSubview:self.portraitView];
// 添加标题,即商户名
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(kPortraitMargin * 2 + kPortraitWidth, kPortraitMargin, kTitleWidth, kTitleHeight)];
self.titleLabel.font = [UIFont boldSystemFontOfSize:14];
self.titleLabel.textColor = [UIColor whiteColor];
self.titleLabel.text = @"titletitletitletitle";
[self addSubview:self.titleLabel];
// 添加副标题,即商户地址
self.subtitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(kPortraitMargin * 2 + kPortraitWidth, kPortraitMargin * 2 + kTitleHeight, kTitleWidth, kTitleHeight)];
self.subtitleLabel.font = [UIFont systemFontOfSize:12];
self.subtitleLabel.textColor = [UIColor lightGrayColor];
self.subtitleLabel.text = @"subtitleLabelsubtitleLabelsubtitleLabel";
[self addSubview:self.subtitleLabel];
}
// 传递数据
- (void)setTitle:(NSString *)title {
self.titleLabel.text = title;
}
- (void)setSubtitle:(NSString *)subtitle {
self.subtitleLabel.text = subtitle;
}
- (void)setImage:(UIImage *)image {
self.portraitView.image = image;
}
// 控件背景的绘制
#define kArrorHeight 10
- (void)drawRect:(CGRect)rect {
[self drawInContext:UIGraphicsGetCurrentContext()];
self.layer.shadowColor = [[UIColor blackColor] CGColor];
self.layer.shadowOpacity = 1.0;
self.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
}
- (void)drawInContext:(CGContextRef)context {
CGContextSetLineWidth(context, 2.0);
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:0.8].CGColor);
[self getDrawPath:context];
CGContextFillPath(context);
}
- (void)getDrawPath:(CGContextRef)context {
CGRect rrect = self.bounds;
CGFloat radius = 6.0;
CGFloat minx = CGRectGetMinX(rrect),
midx = CGRectGetMidX(rrect),
maxx = CGRectGetMaxX(rrect);
CGFloat miny = CGRectGetMinY(rrect),
maxy = CGRectGetMaxY(rrect)-kArrorHeight;
CGContextMoveToPoint(context, midx+kArrorHeight, maxy);
CGContextAddLineToPoint(context,midx, maxy+kArrorHeight);
CGContextAddLineToPoint(context,midx-kArrorHeight, maxy);
CGContextAddArcToPoint(context, minx, maxy, minx, miny, radius);
CGContextAddArcToPoint(context, minx, minx, maxx, miny, radius);
CGContextAddArcToPoint(context, maxx, miny, maxx, maxx, radius);
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
CGContextClosePath(context);
}
@end
以上就是自定义气泡的全部过程,但是为了在点击标注时,弹出自定义的气泡,还需要自定义AnnotationView。步骤如下:
#import "CustomAnnotationView.h"
@interface CustomAnnotationView ()
@property (nonatomic, strong) CustomCalloutView *calloutView;
@end
@implementation CustomAnnotationView
#define kCalloutWidth 200.0
#define kCalloutHeight 70.0
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
if (self.selected == selected) {
return;
}
if (selected) {
if (self.calloutView == nil) {
self.calloutView = [[CustomCalloutView alloc] initWithFrame:CGRectMake(0, 0, kCalloutWidth, kCalloutHeight)];
self.calloutView.center = CGPointMake(CGRectGetWidth(self.bounds) / 2.f + self.calloutOffset.x, -CGRectGetHeight(self.calloutView.bounds) / 2.f + self.calloutOffset.y);
}
self.calloutView.image = [UIImage imageNamed:@"category_3"];
self.calloutView.title = self.annotation.title;
self.calloutView.subtitle = self.annotation.subtitle;
[self addSubview:self.calloutView];
}else {
[self.calloutView removeFromSuperview];
}
[super setSelected:selected animated:animated];
}
@end
ViewController.m
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id)annotation
{
if ([annotation isKindOfClass:[MAPointAnnotation class]])
{
static NSString *reuseIndetifier = @"annotationReuseIndetifier";
CustomAnnotationView *annotationView = (CustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
if (annotationView == nil)
{
annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseIndetifier];
}
annotationView.image = [UIImage imageNamed:@"category_3"];
// 设置为NO,用以调用自定义的calloutView
annotationView.canShowCallout = NO;
// 设置中心点偏移,使得标注底部中间点成为经纬度对应点
annotationView.centerOffset = CGPointMake(0, -18);
return annotationView;
}
return nil;
}