代码地址如下:
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. [thinkphp] 是如何输出一个页面的

    表面上看,TP输出一个页面很简单:$this->display(); 实际上是怎么回事呢?$this->display(); 这个display()方法是定义在ThinkPHP/Libra ...

  2. 20180824Noip模拟赛10分总结

    嗯,总之,是我太傻了. 我真傻,真的,我单知道最小生成树,却不知道还有最大生成树 T1 最大生成树.... 累加每一个环内,最大生成树的边权,(对环求最大生成树,则必然剩下一个边权最小的边(因为是求生 ...

  3. Codeforces #430 Div2 D

    #430 Div2 D 题意 给出一些数,每次操作先将所有数异或一个值,再求这些数中没有出现过的最小的非负整数. 分析 对于更新操作,对于 \(x\) 所有为 \(1\) 的位给相应层添加一个标记,当 ...

  4. IDEA的Maven项目找不到class

  5. 【分块】bzoj1798 [Ahoi2009]Seq 维护序列seq

    分块,打标记,维护两个标记:乘的 和 加的. 每次 区间乘的时候,对 乘标记 和 加标记 都 乘上那个值. 每次 区间加的时候 对 加标记 加上那个值. (ax+b)*v=axv+bv.开 long ...

  6. 【bzoj1486】【[HNOI2009]梦幻布丁】启发式链表合并(详解)

    (画师当然是武内崇啦) Description N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3 ...

  7. STL之vector2

    描述 依次输入n个整数,每次输入时检查该值是否已经出现在vector中,如果存在则不插入,否则将其插入到开头位置. 部分代码已经给出,请补充完整,提交时请勿包含已经给出的代码. int main() ...

  8. C#Windows服务:一些方法(启动、停止等)

    前面讲述了如何创建和安装服务(创建windows服务),下面把启动.停止.判断是否启动的方法也写一下. /// <summary> /// 判断是否安装了某个服务 /// </sum ...

  9. IntelliJ IDEA强制更新Maven的包

    1.手动删除Project Settings里面的Libraries内容,[Ctrl]+[Alt]+[Shift]+[S],全选之后点击左上角的减号按钮. 2.在Maven Project的试图里的L ...

  10. CSS部分属性的深入学习

    先上个张鑫旭大神的政治课,来个一棒打醒(手动滑稽): 说说CSS学习中的瓶颈: 虽然自己水平不高,但是对于重构这方面工作一直不怎么喜欢,可能觉得比较没有新意,但是看了大神文章突然有点一棍打醒的感觉,突 ...