原文连接http://blog.youkuaiyun.com/xf931456371/article/details/51348814
一 地图的基本使用
1 地图需要依赖的框架 : MapKit
2 框架基本作用 : 用于地图展示,例如大头针,路线、覆盖层展示等(着重界面展示)
3 使用步骤 :
—-> 3.1 导入头文件 : import MapKit(swift) ; #import
—-> 3.2 MapKit有一个比较重要的UI控件 :MKMapView,专门用于地图显示
4 设置地图显示类型
—-> 4.1 地图的样式可以手动设置, 在iOS9.0之前有3种, iOS9.0之后增加了2种
<code class="hljs mathematica has-numbering"> Standard :普通地图
Satellite : 卫星云图
Hybrid : 普通 + 卫星云图
SatelliteFlyover ios9<span class="hljs-number">.0</span> <span class="hljs-number">3</span><span class="hljs-keyword">D</span>立体
HybridFlyover ios9<span class="hljs-number">.0</span> <span class="hljs-number">3</span><span class="hljs-keyword">D</span>立体混合</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>
—-> 4.2 设置方式
<code class="hljs avrasm has-numbering">mapView<span class="hljs-preprocessor">.mapType</span> = <span class="hljs-preprocessor">.HybridFlyover</span></code><ul style="" class="pre-numbering"><li>1</li></ul>
5 设置地图的控制项(包括 : 地图的旋转, 缩放, 移动等等操作行为都可以开启或者关闭)
—-> 5.1 设置方式 :
<code class="hljs cs has-numbering"> mapView.scrollEnabled = <span class="hljs-keyword">false</span> <span class="hljs-comment">//滚动</span>
mapView.rotateEnabled = <span class="hljs-keyword">false</span> <span class="hljs-comment">//旋转</span>
mapView.zoomEnabled = <span class="hljs-keyword">false</span> <span class="hljs-comment">//缩放 缩放和滚动默认是有的</span>
mapView.pitchEnabled = <span class="hljs-keyword">false</span> <span class="hljs-comment">//3D</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>
6 设置地图的显示项(包括 : 地图上的指南针, 比例尺, 建筑物, POI点都可以控制是否显示)
—-> 6.1 设置方式 :
<code class="hljs cs has-numbering"> <span class="hljs-keyword">if</span> <span class="hljs-preprocessor">#available(iOS 9.0, *) {</span>
mapView.showsCompass = <span class="hljs-keyword">true</span> <span class="hljs-comment">//显示指南针</span>
mapView.showsScale = <span class="hljs-keyword">true</span> <span class="hljs-comment">//显示比例尺</span>
mapView.showsTraffic = <span class="hljs-keyword">true</span> <span class="hljs-comment">//显示交通</span>
}
mapView.showsBuildings = <span class="hljs-keyword">true</span> <span class="hljs-comment">//显示建筑物</span>
mapView.showsPointsOfInterest = <span class="hljs-keyword">true</span> <span class="hljs-comment">//显示兴趣点</span>
mapView.showsUserLocation = <span class="hljs-keyword">true</span> <span class="hljs-comment">//显示用户</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>
7 测试的时候常见的问题
—-> 7.1 为什么地图加载不显示? 解答 : 检查网络是否通畅
—-> 7.2 为什么地图放的太大都是格子, 禁止浏览? 解答 : 正常, 为了安全等原因, 不会看的太详细
—-> 7.3 为什么地图运行起来APP占用内存非常大? 解答 : 正常, 地图加载了很多资源
8 测试所需要的环境
—-> 8.1 加载地图数据需要联网
—-> 8.2 XCode版本根据测试选择不同版本(iOS9.0 只能使用 XCode7.0版本)
—-> 8.3 iOS系统版本根据测试选择不同版本(例如地图类型, 在iOS9.0之后才有新增)
9 地图显示用户的位置
—-> 9.1 可以设置显示用户当前所在位置, 以一个蓝点的形式呈现在地图上(注意 : 如果要显示用户位置, 在iOS8.0之后, 需要主动请求用户授权)
—-> 9.2 设置方式 : (两种)
<code class="hljs cs has-numbering"><span class="hljs-comment">//1. 显示用户的位置后,地图并不跟着用户的位置的改变而改变视角</span>
mapView.showsUserLocation = <span class="hljs-keyword">true</span> <span class="hljs-comment">//显示用户</span>
<span class="hljs-comment">//2. 显示用户的位置之后,地图会跟随着用户的位置,一直让用户的位置显示在地图的中心,当时不灵活</span>
mapView.userTrackingMode = .FollowWithHeading</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>
—-> 9.3 两种方式呈现出来的效果 : 方式一产生效果 : 会在地图上显示一个蓝点, 标识用户所在位置; 但地图不会缩放, 而且当用户位置移动时, 地图不会跟随用户位置移动而移动; 方式二产生效果 : 会在地图上显示一个蓝点, 标识用户所在位置; 而且地图缩放到合适比例,显示用户位置, 当用户位置移动时, 地图会跟随用户位置移动而移动; 但是有时候失效.
—-> 9.4 测试的时候可能会出现的问题 : 用户位置不显示?
—-> 9.5 可能原因 : 1> 检查代码, 是否有设置显示用户位置,是否有进行请求位置授权 2> 查看模拟器是否有位置信息 3> 模拟器的问题
二 用户位置追踪
1 在storyboard中拖拽一个现实地图的UI控件
2 直接在storyboard中设置代理
3 导入框架
4 实现代理方法
5 具体代码 :
—-> 5.1 懒加载
<code class="hljs cs has-numbering"><span class="hljs-comment">//懒加载</span>
<span class="hljs-keyword">private</span> lazy <span class="hljs-keyword">var</span> location : CLLocationManager = {
<span class="hljs-keyword">let</span> location = CLLocationManager()
<span class="hljs-keyword">if</span> <span class="hljs-preprocessor">#available(iOS 8.0, *) {</span>
location.requestAlwaysAuthorization()
}
<span class="hljs-keyword">return</span> location
}()</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>
—-> 5.2 地图的相关设置
<code class="hljs avrasm has-numbering">override func viewDidLoad() {
super<span class="hljs-preprocessor">.viewDidLoad</span>()
mapView<span class="hljs-preprocessor">.showsBuildings</span> = true
if <span class="hljs-preprocessor">#available(iOS 9.0, *) {</span>
mapView<span class="hljs-preprocessor">.mapType</span> = <span class="hljs-preprocessor">.HybridFlyover</span>
}
mapView<span class="hljs-preprocessor">.mapType</span> = <span class="hljs-preprocessor">.Standard</span>
mapView<span class="hljs-preprocessor">.showsUserLocation</span> = true
_ = location
mapView<span class="hljs-preprocessor">.userTrackingMode</span> = <span class="hljs-preprocessor">.FollowWithHeading</span>
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul>
—-> 5.3 代理方法
<code class="hljs cs has-numbering">extension ViewController : MKMapViewDelegate {
<span class="hljs-comment">//当地图获取到用户的位置的时候回调用该方法</span>
func mapView(mapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation) {
<span class="hljs-comment">//MKUserLocation 大头数据模型 只要遵守了MKAnnotation就是大头针数据模型</span>
<span class="hljs-comment">//获取用户的大头针数据模型</span>
userLocation.title = <span class="hljs-string">"肖锋"</span>
userLocation.subtitle = <span class="hljs-string">"你好吗????"</span>
<span class="hljs-comment">//获取用户当前的中心位置</span>
<span class="hljs-keyword">let</span> center = userLocation.location?.coordinate
mapView.setCenterCoordinate(center!, animated: <span class="hljs-keyword">true</span>)
<span class="hljs-comment">//改变显示区域</span>
<span class="hljs-keyword">let</span> span = MKCoordinateSpanMake(<span class="hljs-number">0.162493481087147</span>, <span class="hljs-number">0.10857004327103</span>)
<span class="hljs-keyword">let</span> region = MKCoordinateRegionMake(center!, span)
mapView.setRegion(region, animated: <span class="hljs-keyword">true</span>)
}
<span class="hljs-comment">//当区域改变的时候会调用该方法</span>
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
print(mapView.region.span)
}
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li></ul>
6 大头针数据模型的详细解答
—-> 6.1 MKUserLocation : 被称作“大头针(数据)模型”( 其实喊什么都行,本质就是一个数据模型,只不过此模型遵循了大头针要遵循的协议(MKAnnotation))
—-> 6.2 重要属性 : location : 用户当前所在位置信息(CLLocation对象) ;title : 大头针标注要显示的标题(NSString对象) ; subtitle : 大头针标注要显示的子标题(NSString对象).
7 测试的时候可能会出现的问题
—-> 7.1 地图上的蓝点为什么不显示? 解答 : (1) 确定代码是否有误(例如, 是否显示了用户位置); (2) 确定模拟器是否设置位置 ; (3) 看下位置在哪, 是不是不在当前地图显示区域
—-> 7.2 地图跨度设置之后, 最终显示的跨度和设置数值不一致? 解答 : 因为地球的不是正方形的, 随着用户的位置移动, 会自动修正地图跨度, 保持地图不变形;
三 大头针的使用
1 大头针的理论依据 : 按照MVC原则
—-> 1.1 在地图上操作大头针,实际上是控制大头针的数据模型
—-> 1.2 添加大头针就是添加大头针数据模型
—-> 1.3 删除大头针就是删除大头针数据模型
2 需要实现如图功能(简单)

3 定义模型(必须遵守MKAnnotation协议)
—-> 3.1 创建遵守MKAnnotation的模型文件

—-> 3.2 该模型中需要的属性
<code class="hljs javascript has-numbering">import MapKit
<span class="hljs-keyword">class</span> XFJAnnotation: NSObject , MKAnnotation {
<span class="hljs-comment">//位置坐标</span>
<span class="hljs-keyword">var</span> coordinate : CLLocationCoordinate2D = CLLocationCoordinate2DMake(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)
<span class="hljs-comment">//标题和子标题</span>
<span class="hljs-keyword">var</span> title : <span class="hljs-built_in">String</span>?
<span class="hljs-keyword">var</span> subtitle : <span class="hljs-built_in">String</span>?
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>
—-> 3.3 通过拖线的方式拿到storyboard中的map
<code class="hljs vala has-numbering"> <span class="hljs-comment">//拿到地图</span>
@IBOutlet <span class="hljs-keyword">weak</span> <span class="hljs-keyword">var</span> mapView: MKMapView!</code><ul style="" class="pre-numbering"><li>1</li><li>2</li></ul>
—-> 3.4 点击屏幕获取
<code class="hljs cs has-numbering"><span class="hljs-comment">//点击屏幕获取</span>
<span class="hljs-keyword">override</span> func touchesBegan(touches: Set<UITouch>, withEvent <span class="hljs-keyword">event</span>: UIEvent?) {
<span class="hljs-comment">//获取点</span>
<span class="hljs-keyword">let</span> point = touches.first?.locationInView(mapView)
<span class="hljs-comment">//将试图上的点转化为经度和纬度</span>
<span class="hljs-keyword">let</span> coodinate = mapView.convertPoint(point!, toCoordinateFromView: mapView)
<span class="hljs-comment">//添加大头针</span>
<span class="hljs-keyword">let</span> annotation = addAnntation(coodinate, title: <span class="hljs-string">"肖锋"</span>, subtitle: <span class="hljs-string">"嘿嘿!!!"</span>)
<span class="hljs-comment">//反地理编码获取详细信息</span>
<span class="hljs-keyword">let</span> location = CLLocation(latitude: coodinate.latitude, longitude: coodinate.longitude)
geoc.reverseGeocodeLocation(location) { (clplc : [CLPlacemark]?, error : NSError?) -> Void <span class="hljs-keyword">in</span>
<span class="hljs-comment">//检查内容是否为空</span>
guard <span class="hljs-keyword">let</span> clplc = clplc <span class="hljs-keyword">else</span> {<span class="hljs-keyword">return</span>}
guard <span class="hljs-keyword">let</span> clplcs = clplc.first <span class="hljs-keyword">else</span> {<span class="hljs-keyword">return</span>}
<span class="hljs-comment">//设置大头针的标题和子标题</span>
annotation.title = clplcs.locality
annotation.subtitle = clplcs.name
}
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li></ul>
—-> 3.4 移动屏幕移除所有的大头针
<code class="hljs cs has-numbering"> <span class="hljs-comment">//移动屏幕移除所有的大头针</span>
<span class="hljs-keyword">override</span> func touchesMoved(touches: Set<UITouch>, withEvent <span class="hljs-keyword">event</span>: UIEvent?) {
<span class="hljs-comment">//取出所有的大头针</span>
<span class="hljs-keyword">let</span> annotation = mapView.annotations
<span class="hljs-comment">//移除有所的大头针</span>
mapView.removeAnnotations(annotation)
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul>
—-> 3.5 通过一个方法创建大头针
<code class="hljs cs has-numbering"><span class="hljs-comment"><span class="hljs-xmlDocTag">///</span>MARK : - 创建大头针</span>
extension ViewController {
<span class="hljs-keyword">private</span> func <span class="hljs-title">addAnntation</span>(coordinate : CLLocationCoordinate2D, title : String?, subtitle : String?) ->XFJAnnotation
{
<span class="hljs-comment">//创建大头针</span>
<span class="hljs-keyword">let</span> annotation = XFJAnnotation()
<span class="hljs-comment">//设置标题</span>
annotation.title = title
annotation.subtitle = subtitle
<span class="hljs-comment">//设置大头针的位置</span>
annotation.coordinate = coordinate
<span class="hljs-comment">//添加大头针</span>
mapView.addAnnotation(annotation)
<span class="hljs-comment">//返回大头针</span>
<span class="hljs-keyword">return</span> annotation
}
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li></ul>
4 可能会出现的问题
—-> 4.1 反地理编码无法获取对应的数据 ? 原因 : (1) 检查是否有联网 (2) 检查代码是否有误 (3) 有时存在某些位置没有反地理编码结果, 换个点尝试, 如果都没有, 排除此原因
四 大头针的添加和删除
1 当代码执行到下面这一句的时候,会调用一个代理方法
<code class="hljs cs has-numbering"><span class="hljs-comment">//添加大头针</span>
<span class="hljs-comment">/*
当创建一个大头针数据模型添加到地图上之后,会执行对应的代理方法,在代理方法中查找对应的大头针视图
*/</span>
mapView.addAnnotation(annotation)</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>
—-> 1.1 会调用的代理方法(大头针的相关设置)
<code class="hljs cs has-numbering">extension ViewController : MKMapViewDelegate {
<span class="hljs-comment">//当添加一个大头针数据模型,会调用该方法,寻找对应的大头针视图并返回,如果此处返回的是nil,代表使用系统默认的大头针</span>
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
<span class="hljs-comment">//创建标识</span>
<span class="hljs-keyword">let</span> pinID = <span class="hljs-string">"pinID"</span>
<span class="hljs-comment">//从缓存池中通过标识取出大头针视图</span>
<span class="hljs-keyword">var</span> pinAnntationView = mapView.dequeueReusableAnnotationViewWithIdentifier(pinID) <span class="hljs-keyword">as</span>? MKPinAnnotationView
<span class="hljs-comment">//判断大头针是否为空</span>
<span class="hljs-keyword">if</span> pinAnntationView == nil {
pinAnntationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: pinID)
}
<span class="hljs-comment">//设置数据模型(必须设置的)</span>
pinAnntationView?.annotation = annotation
<span class="hljs-comment">//运行弹框</span>
pinAnntationView?.canShowCallout = <span class="hljs-keyword">true</span>
<span class="hljs-comment">//设置大头针的颜色</span>
pinAnntationView?.pinTintColor = UIColor.redColor()
<span class="hljs-comment">//设置大头针的下落动画</span>
pinAnntationView?.animatesDrop = <span class="hljs-keyword">true</span>
<span class="hljs-comment">//拖动大头针顶视图</span>
pinAnntationView?.draggable = <span class="hljs-keyword">true</span>
<span class="hljs-comment">//返回大头针视图</span>
<span class="hljs-keyword">return</span> pinAnntationView
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li></ul>
—-> 1.2 拖动或者选中大头针的时候会调用(都是代理方法)
<code class="hljs scss has-numbering"><span class="hljs-comment">//当拖动大头针视图的时候会调用</span>
func <span class="hljs-function">mapView(mapView: MKMapView, annotationView view: MKAnnotationView, didChangeDragState newState: MKAnnotationViewDragState, fromOldState oldState: MKAnnotationViewDragState)</span> {
<span class="hljs-function">print(newState.rawValue,oldState.rawValue)</span>
}
<span class="hljs-comment">//当选中大头针的时候会调用</span>
func <span class="hljs-function">mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView)</span> {
<span class="hljs-function">print(<span class="hljs-string">"选中了\(view.annotation!.title)"</span>)</span>
}
<span class="hljs-comment">//当反选中大头针的时候回调用</span>
func <span class="hljs-function">mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView)</span> {
<span class="hljs-function">print(<span class="hljs-string">"反选中了\(view.annotation?.title)"</span>)</span>
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul>
五 大头针的头像设置(左右头像设置)
1 直接在第一个代理方法中拿到大头针进行设置
<code class="hljs cs has-numbering"><span class="hljs-comment">//大头针的左边视图</span>
<span class="hljs-keyword">let</span> image = UIImage(named: <span class="hljs-string">"Snip20160508_1"</span>)
<span class="hljs-keyword">let</span> imageView = UIImageView(frame: CGRectMake(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">50</span>, <span class="hljs-number">50</span>))
imageView.image = image
pinAnntationView?.leftCalloutAccessoryView = imageView
<span class="hljs-comment">//大头针的右边视图</span>
<span class="hljs-keyword">let</span> image1 = UIImage(named: <span class="hljs-string">"Snip20160508_2"</span>)
<span class="hljs-keyword">let</span> imageView1 = UIImageView(frame: CGRectMake(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">60</span>, <span class="hljs-number">60</span>))
imageView1.image = image1
pinAnntationView?.rightCalloutAccessoryView = imageView1</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>
六 大头针的定位追踪
1 执行程序后的图片(红色标明的部分)

<code class="hljs cs has-numbering"><span class="hljs-keyword">override</span> func viewDidLoad() {
super.viewDidLoad()
<span class="hljs-keyword">let</span> userTrackingItem = MKUserTrackingBarButtonItem(mapView: mapView)
navigationItem.rightBarButtonItem = userTrackingItem
_ = location
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>
七 总结
1 这篇博客我只是简单的说明了关于地图的基本使用,具体的实现场景我得为大家写上地图在app上的具体实现,将在后续为大家介绍.(以上内容只提供给初学者学习,当然如果您有很久的开发经验,麻烦您多多赐教).
2 最后,大家如果觉得我写的博客还行的话,麻烦大家多多关注我的官方博客,谢谢!!!!