代码地址如下:
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. 《Java并发编程实战》学习笔记

    第2章 线程安全性 正确性: 某个类的行为与其规范完全一致. 2.1线程安全: 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或 ...

  2. 详解cookie与session的区别,讲得最透彻的一篇文章

    在PHP面试中 经常碰到请阐述session与cookie的区别与联系,以及如何修改两者的有效时间. 大家都知道,session是存储在服务器端的,cookie是存储在客户端的,session依赖于c ...

  3. django 实现自定义认证

    1.Django自带用户认证系统 Django自带用户认证系统,这个系统支持访问控制.注册用户.关联创建者和内容等:在开发用户认证功能时的时候,可以使用Django自带用户认证系统实现: A.相关表 ...

  4. bufferknife框架的正确使用方式 -终于他么知道了

    1.由于ButterKnife从7.x到8.x后,运行时和编译器被分开来,你还需要配置 apt ‘com.jakewharton:butterknife-compiler:8.1.0’,在projec ...

  5. dutacm.club Water Problem(矩阵快速幂)

    Water Problem Time Limit:3000/1000 MS (Java/Others)   Memory Limit:163840/131072 KB (Java/Others)Tot ...

  6. 细菌(disease) (位运算)(状态压缩)

    细菌(disease) 时间限制: 1 Sec  内存限制: 64 MB提交: 9  解决: 5[提交][状态][讨论版] 题目描述 近期,农场出现了D(1≤D≤15)种细菌.John要从他的N(1≤ ...

  7. 12、Flask实战第12天:子域名

    什么是子域名,我们的后台管理系统, 比如cms.heboan.com.配置子域名需要用到蓝图技术: 我现在buleprints下面创建一个cms.py 蓝图 from flask import Blu ...

  8. POJ 3293 Rectilinear polygon(几何基础)

    [题目链接] http://poj.org/problem?id=3293 [题目大意] 给出一些点,每个点只能向外引出一条平行X轴,和Y轴的边, 问能否构成一个闭多边形,如果能,返回多边形的总边长, ...

  9. [AGC012F]Prefix Median

    题目大意: 给定一个长度为$2n-1(n\le50)$的数组$a$,可以重排$a$中的元素,生成一个长度为$n$的数组$b$,其中$b_i$为$a_1\sim a_{2i-1}$的中位数.求对于给定的 ...

  10. Delphi 7生成XML

    文件格式为: Day 制1課 U12 ASSY01 Wrist 1009 0 2018/05/18 09:35:59 Day 制1課 U12 ASSY02 Wrist 1010 0 2018/05/1 ...