iOS地图开发进阶

之前的文章里写了Mapkit的基本使用,定位,大头针,画线等等,但是因为年代久远,写的时候还是Google地图,且很多API也都停用了,所以现在新写个关于地图的开发文章,目的一是为了复习且对比新旧地图API的区别,目的二是使用一些进阶的功能,比如OverLay元素的用法

参考:raywenderlich地图教程    ;    raywenderlich地图Overlay教程

设定一个Region

从最基础的开始,创建一个MapView不必多说,如果你开启了定位,默认会显示当前国家的,那么要精确的显示某个经纬度为中心一个范围的地方怎么办呢,以前的文章写过使用Map的setRegion方法,现在也如此,只不过用一个方便的方法MKCoordinateRegionMakeWithDistance可以以米为单位设定一个Region

上面的代码坐标是Honolulu,运行就可以显示一个区域的地图了

增加一个标记

增加一个简单的大头针,设定了title和subtitle在点击的时候可以看到基本信息

自定义Annotation类

为了方便,可以自己写一个Annotation,但并不是简单地Annotation的子类,因为Annotation是一个协议,这个协议coordinate是必须的,title和subtitle是可选的,下面自定义一个叫做ArtWork的标记

重用标记

标记是可以重用的,就像UITableview的cell一样,看不见的Annotation就像看不见的Cell一样,内存会给看得见的继续使用

前面说了自己定义一个类可以作为Annotation,但实际上,如果想自定义视图得使用MKMapViewDelegate协议的viewForAnnotation方法,这个方法返回MKAnnotationView,到这里有点晕了,现在出现了MKAnnotation, MKPointAnnotation, MKAnnotationView,之前的文章里还有个MKPinAnnotationView,这四个到底是什么关系?

MKAnnotation是一个协议,刚才创建的ArtWork就是一个遵循MKAnnotation协议的类。可以只把MKAnnotation看成数据源,和界面无关

MKPointAnnotation继承自MKShape,也是一个遵循MKAnnotation协议的NSObject,所以MKPointAnnotation就是一个封装好了的默认的标记,便于直接使用

MKAnnotationView是用来定义标记的视图具体怎么展现,更加灵活,如果很多标记都是长一个样子,那么MKAnnotationView可以像UITableviewCell一样被重用,所以一个MKAnnotationView可以用于展现多个Annotation(具体来说就是实现了MKAnnotation协议的类,且还没出现在屏幕里的)

MKPinAnnotationView是一个封装好的MKAnnotationView的子类,默认的大头针视图,用起来方便

好,理清了这些关系,我们现在开始使用代理方法添加重用的Annotation,正常情况下,应该直接在我们的ViewController上面遵循MKMapVIewDelegate协议,然后实现viewForAnnotation方法,但是这里为了代码解耦,使用extension这个Swift特性把协议给分离出来

随便建一个Swift文件,实现下面代码

可以看到创建一个新的MKPinAnnotationView的时候,有rightCalloutAccessoryView属性,这个一般用于添加一个按钮,可以看这个Annotation的详细信息用的,此外还有类似tableView的dequeueReusableAnnotationViewWithIdentifier方法,这点使用上基本和tableview一样的重用机制

Run一下,就像这样

IMG_5409

标记的accessory按钮点击

这个也是利用代理方法

简单的Overlay

下面记录一下如何给地图添加overlay,比如自定义图片,一个小汽车,或者一只猫

那么首先说一下Overlay比较基础的知识

Overlay是什么?Overlay告诉Mapkit如何添加地图上的自定义图像,使用OVerlay需要三个步骤

  1. 创建一个自定义类遵循Overlay protocol,必须实现两个属性coordinate和boundingMapRect,这个很好理解,坐标和尺寸决定了Overlay可以随着地图交互缩放
  2. 实例化这个自定义的类,不同的地点要实例化不同的自定义类
  3. MapView添加这个Overlay类

但是这是不足以实现一个自定义图像覆盖地图效果的,因为Overlay本身是个协议不是类,真真正正添加到地图上面的得是一个View,这时候就需要MKOverlayRenderer,需要通过Map的代理方法来返回它,且MKOverlayRenderer初始化的时候需要Overlay,通过MKOverlayRenderer来显示添加到上面的自定义视图,但是要注意不可直接添加MKOverlayRenderer到Map,必须使用

好,知道了要使用Overlay和OverlayRenderer这两个重要的组成来显示添加视图,那么现在就创建这两个类

//Overlay

//OverlayRenderer

创建完了Overlay和OverlayRenderer下面就可以在地图上添加自定义视图了

首先在地图Controller里添加下面这个方法

那么地图就添加了Overlay对象,但是这是不够的,要想能看到Overlay需要实现上文说的代理方法

下面Run一下就可以看到地图上面多了一只小狗了,而且无论怎么缩放或者旋转地图,小狗也会跟着旋转,Overlay的厉害之处体现,相比于扣一个图片上去,可以随着地图完美融合,这适合于固定的一个地点标记,一个地图示例点,这点和Annotation有区别,下面会讲

IMG_5955IMG_5956

这样一个简单的Overlay就添加完了

再述Annotation

前面虽然说了Annotation,现在感觉说的有点乱,这里按照Overlay重新强调一遍,Annotation就像Overlay,是一个协议,AnnotationView就像OverlayRenderer真正用于展示。

自定义Annotation

自定义AnnotationView

很像Overlay对吧,然后添加add Annotations 代码

这里截图说一下Annotation和Overlay的区别,同样是覆盖物有什么不同呢?

IMG_5957 IMG_5958

可以看到,无论地图怎么旋转缩放,Annotation都是不跟着形变的,就像大头针一样钉在那里,就是和Overlay的区别,更“专注”

接下来研究画图形

用MKPolyLine画线

那么还是根据raywenderlich教程的顺序,也是循序渐进的方法,从最简单的画线开始,我们将用MKPolyLine去连接地图上的一系列坐标点

和上面的教程一样,项目里导入一个plist文件,里面是一系列的经纬度坐标,下面添加代码

首先画线是一个overlay,因为线会随着地图缩放旋转也产生形变,是跟随同步的,那么首先就得给地图添加overlay,实际上MKPolyLine这个类本身就是一个遵循Overlay的自定义类,就像上面Overlay教程中说的一样,只不过苹果帮助我们封装好了,可以直接初始化使用,添加到Map上

下一步是什么呢,没错儿,一样的套路,实现一个返回OverlayRenderer的代理方法,把之前的代码添加一个MKPolyline的判断

同理可以看到MKPolylineRenderer也已经定义好了,可以直接用,下面Run一下,地图上应该就出现线路图了,可以用于记录行车轨迹,待实验,可以注意到Overlay和route都显示了

IMG_5978

用MKPolygon画闭合多边形

理论上MKPolyline能画所有的多边形,但是对于一些闭合的多边形有更适合的类来处理,比如MKPolygon,MKPolygon就像MKPolyline一样,只不过最后会闭合起始点,形成闭合多边形,例子中刚刚画了mountain park的一条路线,下面画这个公园的边界围栏用MKPolygon就很方便了

因为和MKPolyline一样是一个Overlay,用法也类似,首先给地图添加这个MKPolygon实例

然后返回OverlayRenderer的代理方法里添加MKPolygon这个多边形,用法很类似MKPolylineRenderer

IMG_5982

用MKCircle画圆

好,接下来Overlay类型里应该就缺画圆了,理所当然就用到MKCircle拉。

和其他Overlay使用方法一样,map直接添加MKCircle,但是这里想要给Overlay添加名字和颜色属性,比如可以作为一个人物站在某个位置的标示,那么子类化MKCircle,自己写一个遵循Overlay的自定义类,叫做Character

下面Map添加MKCircle,添加三个人物

下一步修改代理方法,返回OverlayRenderer

OK,Run一下就可以看到地图上指定地点的三个圆形Overlay了

IMG_5983

 

 

 

 

 

 

 

 

 

 

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注