代码地址如下:
http://www.demodashi.com/demo/11682.html

这篇文章还是翻译自raywenderlich,用Objective-C改写了代码。没有逐字翻译,如有错漏,请指出。原文地址在这里

1 概述

MapKit是iOS提供的一个很便捷的API,旨在帮助我们快速开发地理位置相关的应用。在这篇博客中涉及的地方叫Honolulu,是美国的一个城市,中文名是檀香山,是美国夏威夷州首府和港口城市。我第一次听说檀香山应该是在历史书上,似乎跟孙中山先生相关,这里暂时按下不表。

本文的例子中我们要添加一个地图到APP中,然后通过经纬度定位到一个指定的位置,通过大头针的形式来展示定位,点击大头针会显示位置的一些信息。我们可以设置大头针的颜色,当然我们更可以自定义图片来替换默认的大头针,丰富地图内容。

2 开始

首先新建工程,命名为MapKitTutorial,然后添加一个Map Kit View到Storyboard中。先拖拽地图视图到充满屏幕,然后选择添加建议的约束即可,添加完约束效果如图1所示。

然后需要在ViewController.m中添加Map View的outlet关联,通过CTRL+DRAG即可,命名为mapView,代码如下,别忘记引入MapKit头文件,注意要先导入MapKit库(Xcode7.3里面,先选择工程,然后在Capabilities那一项把Maps开关打开):

......
#import <MapKit/MapKit.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet MKMapView *mapView;
@end

这样,我们编译运行项目,可以看到地图出现了,默认显示的是中国地图在中央位置,这个应该是跟系统环境相关。如图2所示:

3 设置可视区域

接下来重点来了,我们要设置一个可视区域。学过地理

的都知道(我是地理盲),一个地理位置我们是通过纬度和经度来确定一个位置,纬度中北纬和南纬各分为90度,经度西经和东经则各为180度。在iOS开发中,北纬和东经我们用正数表示,南纬和西经用负数表示。

接下来我们要设置一个可视区域,不设置我们看到的只是一个默认区域,如前面看到的一样。设置可视区域的代码如下,然后在方法viewDidLoad中加入调用:

- (void)centerMapOnLocation {
//1 设置好纬度和经度
CLLocationCoordinate2D initialLocation = {21.282778, -157.829444};
CLLocationDistance regionRadius = 1000; MKCoordinateRegion coordinateRegion = MKCoordinateRegionMakeWithDistance(initialLocation, regionRadius * 2, regionRadius * 2);
[self.mapView setRegion:coordinateRegion];
}

这里来解析一下,首先是设置好中心点的经纬度。然后是设置区域半径,包括横向和纵向半径,这里都设置的为2000米(南北和东西的跨度范围)。接着根据中心点经纬度和区域半径创建一个Region,最后调用MapView的setRegion方法即可。这时我们再运行代码可以看到效果如图3所示,我们看到与前面不同了,确实地图已经定位到我们设置的中心点和区域大小了:

4 设置标记

接下来来设置一个标记,也就是通常见到的那种大头针。先新建一个类Artwork来表示标记内容,包括位置坐标,标题和副标题等。位置坐标用于确定大头针位置,而标题和副标题则是点击大头针的时候显示的内容。

@interface Artwork : NSObject <MKAnnotation>

@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;
@property (nonatomic, strong) NSString *locationName;
@property (nonatomic, strong) NSString *discipline;
@property (nonatomic) CLLocationCoordinate2D coordinate; - (instancetype)init:(NSString *)title
locationName:(NSString *)locationName
discipline:(NSString *)discipline
coordinate:(CLLocationCoordinate2D)coordinate; @end

类Artwork定义如上所示,然后在ViewController.m中加入添加大头针的代码:

- (void)addAnnotation {
CLLocationCoordinate2D coordinate = {21.283921, -157.831661};
Artwork *artwork = [[Artwork alloc] init: @"King David Kalakaua"
locationName: @"Waikiki Gateway Park"
discipline: @"Sculpture"
coordinate: coordinate];
[self.mapView addAnnotation:artwork];
}

注意这里的坐标暂时是自己手动指定,在后面我们会从一个JSON文件中解析一系列的坐标位置然后设置多个大头针。然后里面的locationName其实是位置名字,而MKAnnotation是一个协议,地图标记的协议,它里面主要定义了一系列的属性值(这里可以发现协议不只有方法,也可以定义属性的),就是标记必须的几个属性title,subtitle,coordinate。

然后在viewDidLoad中加入该方法的调用,可以看到大头针显示,点击可以看到title和subtitle的显示。

仅仅这样当然是不够的,为了APP的个性化,我们希望可以自定义大头针显示方式,可以通过设置ViewController实现协议MKMapViewDelegate,然后将mapView的delegate设置为ViewController,并在ViewController中实现协议的viewForAnnotation方法即可。代码如下:

- (void)viewDidLoad {
[super viewDidLoad];
[self centerMapOnLocation];
[self addAnnotation];
//1新增delegate设置
self.mapView.delegate = self;
} //2 新增代理方法实现
#pragma MKMapViewDelegate
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[Artwork class]]) {
NSString *identifier = @"pin";
MKPinAnnotationView *view = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (!view) {
view = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
//自定义后需要设置canShowCallout为YES,不然点击不会显示信息。
view.canShowCallout = YES;
//设置信息展示偏移
view.calloutOffset = CGPointMake(-10, 5);
//设置信息按钮
view.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
//设置大头针颜色
view.pinTintColor = [UIColor blueColor];
return view;
}
return nil;
}

方法viewForAnnotation中我们定义了大头针的信息偏移和在显示内容中添加了一个信息按钮。偏移位置是针对大头针的中间顶部而言的,这里我们设置信息展示的X轴向左偏移中间位置10个Point,Y轴则从顶部往下移动5个Point,并将大头针的颜色设置为蓝色,运行效果如图5所示。

5 启动地图APP

上一节点击信息按钮,并没有反应,接下来就要加入点击信息按钮的事件响应,这里我们是跳转到地图app中,显示从当前位置到公园的驾驶路线。

首先需要在类Artwork中加入一个方法,用来创建MapItem。这里需要导入Contacts头文件(原文中用的是Address头文件,iOS9以后的系统中已经不用Address,所以我这里用Contacts来替代)。

#import <Contacts/Contacts.h>
- (MKMapItem *)mapItem {
NSDictionary *addressDictionary = @{CNPostalAddressStreetKey: self.locationName};
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:self.coordinate addressDictionary:addressDictionary];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
return mapItem;
}

然后在ViewController中实现另外一个协议方法如下。另外,在Xcode菜单栏的Product\Scheme\Edit Scheme选择Run的Options选项,设置好默认位置为Honolulu,如图6所示。这样点击右侧的信息按钮,就会跳转到地图APP中了(这里可能是由于高德地图问题,显示不了驾驶路线,暂时没有找到解决方法,若有知道的,麻烦告知一声)。

- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
Artwork *artwork = (Artwork *)view.annotation;
NSDictionary *launchOptions = @{MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving};
[[artwork mapItem] openInMapsWithLaunchOptions:launchOptions];
}

运行效果如下:

6 用户位置授权

在iOS应用中,如果应用要请求位置信息,一般是需要提示用户是否授权的,这个功能怎么实现呢?首先在ViewController中加入CLLocationManager,然后在viewDidAppear中加入请求授权的函数调用,如果一次请求授权允许了,系统会记录授权的状态,下次启动应用就不需要再次授权了。如果拒绝授权了,以后要开启只能到系统设置里面开启。

注意:一般请求授权分为两种方式,一种是requestWhenInUseAuthorization表示只有应用在前台允许的时候获取位置信息,而另外一种是requestAlwaysAuthorization表示只要应用在运行就可以获取位置信息,不管在前台还是后台运行,为了不泄露隐私,苹果官方是建议用第一种,即在前台运行的时候运行访问位置信息。

另外一个容易忽视的一点,就是还需要在项目的Info.plist中加入一个配置。配置键名为NSLocationWhenInUseUsageDescription,内容为请求授权的文字信息,本项目填的信息为To show you cool things nearby

@property (strong, nonatomic) CLLocationManager *locationManager;

- (void)checkLocationStatus {
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) {
self.mapView.showsUserLocation = YES;
} else {
[self.locationManager requestWhenInUseAuthorization];
}
}

这样在启动应用的时候,就会弹出一个提示框,内容为应用请求访问您的位置信息,让你决定是否授权。效果如图8所示:

7 其他

原文中还有一节是通过一个JSON文件来设置多个大头针,并根据位置信息不同设置不同的大头针的颜色,与设置一个大头针效果类似,只是多了JSON解析的步骤,这里不再赘述,可以参见我的项目最终代码。

另外,地图里面还可以设置覆盖层(overlay),比如用图片来设置覆盖层,或者设置路径,多边形等,可以源码包看看。

8 项目文件截图



iOS学习笔记-地图MapKit入门

代码地址如下:
http://www.demodashi.com/demo/11682.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

iOS学习笔记-地图MapKit入门的更多相关文章

  1. iOS学习笔记11-多线程入门

    一.iOS多线程 iOS多线程开发有三种方式: NSThread NSOperation GCD iOS在每个进程启动后都会创建一个主线程,更新UI要在主线程上,所以也称为UI线程,是其他线程的父线程 ...

  2. iOS学习笔记20-地图(二)MapKit框架

    一.地图开发介绍 从iOS6.0开始地图数据不再由谷歌驱动,而是改用自家地图,当然在国内它的数据是由高德地图提供的. 在iOS中进行地图开发主要有三种方式: 利用MapKit框架进行地图开发,利用这种 ...

  3. iOS学习笔记-精华整理

    iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始 ...

  4. iOS学习笔记总结整理

    来源:http://mobile.51cto.com/iphone-386851_all.htm 学习IOS开发这对于一个初学者来说,是一件非常挠头的事情.其实学习IOS开发无外乎平时的积累与总结.下 ...

  5. IOS学习笔记48--一些常见的IOS知识点+面试题

      IOS学习笔记48--一些常见的IOS知识点+面试题   1.堆和栈什么区别? 答:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制:对于堆来说,释放工作由程序员控制,容易产生memor ...

  6. iOS学习笔记——AutoLayout的约束

    iOS学习笔记——AutoLayout约束 之前在开发iOS app时一直以为苹果的布局是绝对布局,在IB中拖拉控件运行或者直接使用代码去调整控件都会发上一些不尽人意的结果,后来发现iOS在引入了Au ...

  7. IOS学习笔记25—HTTP操作之ASIHTTPRequest

    IOS学习笔记25—HTTP操作之ASIHTTPRequest 分类: iOS2012-08-12 10:04 7734人阅读 评论(3) 收藏 举报 iosios5网络wrapper框架新浪微博 A ...

  8. IOS学习笔记之关键词@dynamic

    IOS学习笔记之关键词@dynamic @dynamic这个关键词,通常是用不到的. 它与@synthesize的区别在于: 使用@synthesize编译器会确实的产生getter和setter方法 ...

  9. iOS学习笔记10-UIView动画

    上次学习了iOS学习笔记09-核心动画CoreAnimation,这次继续学习动画,上次使用的CoreAnimation很多人感觉使用起来很繁琐,有没有更加方便的动画效果实现呢?答案是有的,那就是UI ...

随机推荐

  1. Docker容器进入的4种方式(转)

    这个文章不错,几种方式及使用范围都讲得清楚. 另外,还有一个文章说了为什么docker中并不合适ssh服务安装的情况. 我现在也是用第四种方式, docker exec -it [docker容器ID ...

  2. thinkphp实现功能:验证码

    1.定义验证码函数 public function verify(){ /** * 在thinkPHP中如何实现验证码 * * ThinkPHP已经为我们提供了图像处理的类库ThinkPHP\Exte ...

  3. HDU 2141 Can you find it?【二分查找是否存在ai+bj+ck=x】

    Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate ...

  4. HDU 1558 Segment set(并查集)

    题意: 给你一些线段的起点和终点的坐标,最后问和某个线段相连的或者间接相连的线段有多少个(包括本身)? P X1 Y1X2 Y2  起点(X1,X2)终点(X2,Y2):按照出现次数依次编号为1,2, ...

  5. ( 转 ) 数据库BTree索引、Hash索引、Bitmap位图索引的优缺点

    测试于:MySQL 5.5.25 当前测试的版本是Mysql 5.5.25只有BTree和Hash两种索引类型,默认为BTree.Oracle或其他类型数据库中会有Bitmap索引(位图索引),这里作 ...

  6. Integer 类和 int 的区别

    http://www.cnblogs.com/ysocean/p/8075676.html public static void main(String[] args) {     Integer i ...

  7. POJ 1486 Sorting Slides(二分图匹配)

    [题目链接] http://poj.org/problem?id=1486 [题目大意] 给出每张幻灯片的上下左右坐标,每张幻灯片的页码一定标在这张幻灯片上, 现在问你有没有办法唯一鉴别出一些幻灯片 ...

  8. 【线性筛】【筛法求素数】【约数个数定理】URAL - 2070 - Interesting Numbers

    素数必然符合题意. 对于合数,如若它是某个素数x的k次方(k为某个素数y减去1),一定不符合题意.只需找出这些数. 由约数个数定理,其他合数一定符合题意. 就从小到大枚举素数,然后把它的素数-1次方都 ...

  9. 【Python笔记】Python语言基础

    Python是一种解释性(没有编译).交互式.面向对象的语言 1.安装python编译器 版本:Python2.7比较普遍,Python不是向下兼容的软件,因此Python3.x有些东西不好找资料 2 ...

  10. IO流--字符流缓冲技术

    缓冲技术是为了提高数据的读写效率而提出的. (1)字符流的缓冲读 在字符流的缓冲技术中提供了一个newLine()方法,这个方法是跨平台的 在读数据的时候采用读完直接刷新的方式可以保证断电后数据不会丢 ...