地图与定位(五)高德地图服务一

序言:

高德地图是一款经常在苹果手机使用的地图平台。在国内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触摸及显示信息比之前更为精准和直观。
好了,不多说,我们下面介绍一下高德地图开放平台为我们提供了哪些支持。


1. 高德地图SDK的集成

高德地图iOS SDK是一套基于 iOS 6.0.0 及以上版本的地图应用程序开发接口,适配armv7、arm64架构,适配iOS9,开启Bitcode。

1.1 成为高德地图开发者。

注册流程就不多做介绍了,按照高德地图开发平台的要求一次操作就好了。

1.2 创建应用,申请 Key。

用户在使用 SDK 时需获取高德地图API Key,不同工程对应不同的Bundle identifer(即安全码),要申请不同Key。

第一步:访问 http://lbs.amap.com/dev/key/,使用高德开发者账号登陆(若不是开发者账号,则会提醒认证成为开发者)。
地图与定位(五)高德地图服务一_第1张图片
第二步:在“应用与权限”页面点击上方的“创建新应用”按钮,依次:输入应用名名称,和应用类型创建应用。
地图与定位(五)高德地图服务一_第2张图片
地图与定位(五)高德地图服务一_第3张图片
第三步:点击“添加新Key”按钮,填入key的名称,选择绑定的服务为“iOS平台SDK”,输入安全码:Bundle Identifier,如下图所示:在当前页面的“Key”列表中中可以看到所申请的Key,如下图所示:
地图与定位(五)高德地图服务一_第4张图片

1.3 环境配置

第一步:引入地图库
将解压后的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”按钮,将资源文件添加到工程中。
地图与定位(五)高德地图服务一_第5张图片

注意: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

说明:

  • 备注中,2D表示使用2D栅格地图需要的系统文件,3D表示使用3D矢量地图需要的系统文件、Search表示使用搜索库需要的系统文件,3D(V3.X.X)表示3D矢量地图V3.0.0以后版本需要新增的库。
  • SystemConfiguration.framework、CoreTelephonySecurity.framework、Security.framework 是为了统计app信息使用。
  • iOS9后,需要把libz.dylib、libstdc++6.09.dylib、libc++.dylib替换成libz.tbd、libstdc++6.09.tbd、libc++.tbd。

引入系统库的操作如下:左侧目录中选中工程名,在TARGETS->Build Settings-> Link Binary With Libaries中点击“+”按钮,在弹出的窗口中查找并选择所需的库(见下表),单击“Add”按钮,将库文件添加到工程中。
地图与定位(五)高德地图服务一_第6张图片
第四步:环境配置;
在TARGETS->Build Settings->Other Linker Flags 中添加-ObjC,C大写。
地图与定位(五)高德地图服务一_第7张图片
注意:V2.3.0(含)之前版本不支持arm64,需在 TARGETS->Build Settings->Architectures 点出选择框,选择 “Other”,将默认值修改为 $(ARCHS_STANDARD_32_BIT)。

1.4 配置文件

为保证SDK的功能在iOS 9中正常使用,需在“Info.plist”中做如下配置,

  • iOS9为了增强数据访问安全,将所有的http请求都改为了https,为了能够在iOS9中正常使用地图SDK,请在”Info.plist”中进行如下配置,否则影响SDK的使用。Xcode9.0之后版本,键入NSAppTransportSecurity字段会自动调整为App Transport Security Settings:
  • 在iOS9中为了能正常调起高德地图App的功能,必须在”Info.plist”中将高德地图App的URL scheme列为白名单,否则无法调起,配置如下:
    地图与定位(五)高德地图服务一_第8张图片

2. 地图显示

利用地图SDK提供的接口,开发者可免费使用高德的地图数据。我们提供的地图SDK有两种:3D矢量地图和2D栅格地图,其中:3D矢量地图的效果炫,用户可自定义的程度高;2D栅格地图包体积小,提供英文地图。还具备以下优秀特质:

  • 丰富的地图数据。我们提供的基础地图数据一共17个级别,包含建筑物、道路、医院、学校等信息。同时,还支持使用MATileOverlay对基础地图数据附加额外的特性,制作自定义特色地图。
  • 多元的覆盖物显示。通过在地图上添加覆盖物可丰富地图显示,优化地图体验,iOS SDK提供覆盖物的种类包括:标注、折线、多边形(凹和凸)、圆、图片。自2.3.0版本起,支持绘制带箭头、带纹理的矢量线,并且能设置线端点和连接处的类型,绘制效果更多元化。
  • 多样的手势操作。支持双指缩放、双击放大、旋转等手势操作,并且有相应的接口来控制手势操作。

    本文主要以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

2.1 地图类型

  • 3D矢量地图SDK提供三种地图类型:

     1)普通地图 MAMapTypeStandard;
     2)卫星地图 MAMapTypeSatellite;
     3)夜间地图 MAMapTypeStandardNight;
    
  • 2D栅格地图SDK提供两种地图类型:

     1)普通地图 MAMapTypeStandard
     2)卫星地图 MAMapTypeSatellite。
    

地图类型切换只需设置相应类型,地图默认显示标准地图,从标准地图切换成卫星地图的方法如下:

_mapView.mapType = MAMapTypeSatellite;

2.2 实时交通图

高德地图 iOS SDK提供北京,上海,广州,深圳,武汉,沈阳,南京,宁波,重庆,杭州,青岛,成都,天津,大连,无锡,西安,石家庄,太原,常州,厦门,长春,福州,珠海,东莞,长沙,苏州,金华,佛山,济南,泉州,西宁,乌鲁木齐,嘉兴,香港,鄂尔多斯,南通,中山,惠州,镇江,郑州,合肥,昆明,德州,朝阳,抚顺,大同,荆州,温州,台州,绍兴,莆田,南平,漳州,宁德,三明,龙岩,烟台,阳江,江门,保定,临沂61个城市及城际间的实时交通路况。
显示实时交通路况的代码如下:

_mapView.showTraffic= YES;

3. 标注 Annotation

标注Annotation,就是地图标注注释,目前提供两种标注:

  • 大头针标注,
  • 自定义标注(包括自定义标注图标和自定义气泡图标)

地图上用“大头针”显示一个带有标题的位置点,大头针展示效果是MAPinAnnotationView,点击大头针弹出气泡,气泡内写着“**”,气泡内信息存储在MAPointAnnotation,在地图上添加一个标注的步骤如下:
1. 定义一个 MAPointAnnotation 对象,添加数据;
2. 使用 MAMapView 的 addAnnotation: 方法添加到地图;
3. 实现 mapView:viewForAnnotation: 代理方法;
4. 在代理内定义 MAPinAnnotationView 对象。

3.1 原生大头针标注

我们先来看一下大头针标注的实现。iOS SDK提供的大头针标注MAPinAnnotationView,通过它可以设置大头针颜色、是否显示动画、是否支持长按后拖拽大头针改变坐标等。在地图上添加大头针标注的步骤如下:

  • 修改ViewController.m文件,在viewDidAppear方法中添加如下所示代码添加标注数据对象。
  • 实现 协议中的 mapView:viewForAnnotation:回调函数,设置标注样式。

示例代码:

#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

3.2 自定义大头针标注

高德地图iOS SDK可自定义标注(包括 自定义标注图标 和 自定义气泡图标),均通过MAAnnotationView来实现。若大头针样式的标注不能满足您的需求,您可以自定义标注图标。步骤如下:

  • 添加标注数据对象,可参考大头针标注的步骤(1)。
  • 导入标记图片文件到工程中。
  • 在 协议的回调函数mapView:viewForAnnotation:中修改 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;
}

运行效果有一个问题,点击位置弹出气泡并不出现。

3.3 自定义气泡

气泡在iOS中又称为callout,它由背景和气泡内容构成,每个气泡显示的内容是根据您的需求定义的,这里我们按照如上图所示的气泡介绍实现一个自定义气泡的步骤:

  • 新建自定义气泡类 CustomCalloutView,继承 UIView。
  • 在 CustomCalloutView.h 中定义数据属性,包含:图片、商户名和商户地址。
  • 在CustomCalloutView.m中重写UIView的drawRect方法,绘制弹出气泡的背景。
  • 定义用于显示气泡内容的控件,并添加到SubView中。
  • 在CustomCalloutView.m中给控件传入数据。

示例代码:
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。步骤如下:

  • 新建类CustomAnnotationView,继承MAAnnotationView或MAPinAnnotationView。若继承MAAnnotationView,则需要设置标注图标;若继承MAPinAnnotationView,使用默认的大头针标注。
  • 重写选中方法setSelected。选中时新建并添加calloutView,传入数据;非选中时删除calloutView。
  • 在MAMapViewDelegate的回调方法mapView:viewForAnnotation中的修改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;
}

你可能感兴趣的:(iOS流媒体开发,地图和定位)