再MapView中添加路径

要想让MapView画路径,必然要传给mapView某些东西,没错,类似Annotation(大头针),添加路径也有类似的操作函数和相应传入CLLocation返回路径的协议方法。

1.搭建界面

拖一个全屏的MapView,连线到controller,如下

1 @property (weak, nonatomic) IBOutlet MKMapView *mapView;

2. 创建一个编码器(地理编码,不要误解)

1 @property (nonatomic, strong) CLGeocoder *geocoder;

并让它成为懒加载对象:

1 - (CLGeocoder *)geocoder
2 {
3     if (!_geocoder) {
4         self.geocoder = [[CLGeocoder alloc] init];
5     }
6     return _geocoder;
7 }

上面这些不走都是无脑完成的,写的多了都轻车熟路。下面才是重头戏。

3. 开始之前先拿到起始点和终点的地理信息再说

(1) 在这之前我们是不是要设置mapView的代理呢

遵守协议

1 @interface ViewController () <MKMapViewDelegate>

设置代理:

1 self.mapView.delegate = self;

(2) 开始干活

 1 NSString *address1 = @"北京";
 2     NSString *address2 = @"上海";
 3
 4     [self.geocoder geocodeAddressString:address1 completionHandler:^(NSArray *placemarks, NSError *error) {
 5         if (error) return;
 6
 7         CLPlacemark *fromPm = [placemarks firstObject];
 8
 9         [self.geocoder geocodeAddressString:address2 completionHandler:^(NSArray *placemarks, NSError *error) {
10             if (error) return;
11
12             CLPlacemark *toPm = [placemarks firstObject];
13
14             [self addLineFrom:fromPm to:toPm];
15         }];
16     }];

有心的同志可能观察到:怎么两个反地理编码是嵌套的。呐,这里是你要注意的,在一个controller中只能同时存在一个地理编码信息。如果反编码完起始点就跳出block,那么当反编码完第二个的时候,第一个就被销毁了。而嵌套block则不会。这里你可以理解为block里面的信息还不归属controller管理。

我们反地理编码得到的总是一系列的符合结果的地理信息数组,但是只有最好的那个才是我们需要的,所以总是取出数组中的第一个object。地理信息的类型是CLPlacemark类型,这个类型在添加大头针的时候肯定不会陌生。它就是封装了地理坐标CLLocationCoordinate的一个类型。

我们通过反地理编码的得到了两个地理信息,那接下来就开始划线吧。方法

addLineFrom:fromPm to:toPm

是我们自己创建的,这样防止一个方法里面放置太多的代码,也实现代码的聚合性(一段代码只实现一个功能)。

4. 实现addLineFrom:(CLPlacemark *)from to:(CLPlacemark *)to

(1) 虽然我们设置了开始和结束,但是我们并没有告诉mapView到底是从"北京"到"上海",还是"上海"到"北京",我们现在设置的信息都只是我们单方面的一厢情愿的。

1     // 方向请求
2     MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
3     // 设置起点
4     MKPlacemark *sourcePm = [[MKPlacemark alloc] initWithPlacemark:fromPm];
5     request.source = [[MKMapItem alloc] initWithPlacemark:sourcePm];
6
7     // 设置终点
8     MKPlacemark *destinationPm = [[MKPlacemark alloc] initWithPlacemark:toPm];
9     request.destination = [[MKMapItem alloc] initWithPlacemark:destinationPm];

传进来的CLPlacemark对象又一次被封装到MKPlacemark中了。这是可以理解的,毕竟MapView和CLLocation还是有一点区别的。

这还没完,到这里我们只是设置了请求(request),还没有请求,下面我们请求设置方向

1     // 方向对象
2     MKDirections *directions = [[MKDirections alloc] initWithRequest:request];

方向,和两个地点都有了,至少我们认为不缺少什么东西了,告诉你方向,从哪里出发,到那里出发,你还不知道怎么走,那你就去死吧。或许你担心可能现在的数据还要进一步封装,但是你并不知道怎么封装,那么我告诉你,到这里已经不需要封装了,我们得到了mapView能识别的数据类型。

(2) 那下面我们开始添加咯

前面我们说过,类似添加大头针的addAnnotation:,这里有一个addOverlay:,只要我们点用这个就能添加路线了。但是添加了显示还是一回事(就向添加普通view时没有设置frame一样,添加了但是没有显示。但是这里缺不是frame的问题,后面会介绍的)。

从我们现在的信息获得路线,调用addOverlay:

1 [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
2 //        NSLog(@"总共%lu条路线",   [response.routes count]);
3
4         // code
5
6 }];

我们调用了MKDirections的方法,你问我为什么是这个?这他妈就是这么用的哪有那么多为什么。

这个方法会帮你计算路线,完事之后还会回调一个block,而得到的路线和其他信息都封装在response中让你操作,同事还烦会给你了错误信息。

那我们就不客气了,解析出路线(路线在iOS中是MKRoute对象)

1 for (MKRoute *route in response.routes) {
2          // 添加路线遮盖
3         [self.mapView addOverlay:route.polyline];
4  }

奥,这里叫路线遮盖,可能你从addOverlay就开始疑问了,为什么不是addRoute?可以这么理解,你添加的路线是盖在mapView上面的,而不是mapView自带的属性。

ok,我们暴力添加了所有得到的路线遮盖,但是运行一下你就知道,并没有显示路线,为什么呢,我们的逻辑到现在都都没有错,难道是哪里错了我不知道?其实是没有错的,是还没完成。

(3) 实现代理方法

需要实现代理方法才能显示。

还记得添加大头针的时候需要实现一个代理方法返回大头针view吗,这里也是

1 #pragma mark - MKMapViewDelegate
2 - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
3 {
4     MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
5     renderer.strokeColor = [UIColor redColor];
6     return renderer;
7 }

就是这个逼,每次调用addOverlay时,都会调用一次这个代理方法。

这个方法传入MapView和录像遮盖overlay,返回MKOverlayRender类型,而MKOverlayRender是第一次出现,是什么鬼?看来得创建MKOverlayRender这个对象并返回他了。

代码中你就看出了,我们并没有用MKOverlayRender这个类型,而是用了MKPolylineRender(MKOverlayRender的子类)。因为MKOverlayRender连个属性都没有。试想一下你添加的路径没有线宽和颜色,那你他妈看得见吗。所以我们使用MKPolylineRender子类。他有一系列的属性(按住command,左键点击MKPolylineRender即可查看)可以设置,根据喜好自己发挥吧。

运行你就发现所言非虚了。

5. 添加大头针

这里纯属拓展

在- (void)addLineFrom:(CLPlacemark *)fromPm to:(CLPlacemark *)toPm方法实现开始时添加代码

 1 // 1.添加2个大头针
 2     LSAnnotation *fromAnno = [[LsAnnotation alloc] init];
 3     fromAnno.coordinate = fromPm.location.coordinate;
 4     fromAnno.title = fromPm.name;
 5     [self.mapView addAnnotation:fromAnno];
 6
 7     LsAnnotation *toAnno = [[LsAnnotation alloc] init];
 8     toAnno.coordinate = toPm.location.coordinate;
 9     toAnno.title = toPm.name;
10     [self.mapView addAnnotation:toAnno];

这里就是纯添加两个大头针,利用传进来的两个地点信息。LsAnnotation时自己创建的实现了<MKAnnotation>协议的大头针,并添加了几个属性,添加出来的就是一个红色的大头针,你想要其他样式请移步到其他教程。

这里给出.h文件,.m文件没有任何实现,所以不给了

1 #import <Foundation/Foundation.h>
2 #import <MapKit/MapKit.h>
3 @interface LsAnnotation : NSObject <MKAnnotation>
4 @property (nonatomic) CLLocationCoordinate2D coordinate;//required
5 @property (nonatomic, copy) NSString *title;
6 @property (nonatomic, copy) NSString *subtitle;
7
8 @end 

ok,结束了。

给出controller的完整代码

  1 //
  2 //  LsViewController.m
  3 //  07-导航画线
  4 //
  5 //
  6
  7 #import "LsViewController.h"
  8 #import "LsAnnotation.h"
  9 #import <MapKit/MapKit.h>
 10 #import <CoreLocation/CoreLocation.h>
 11
 12 @interface MJViewController () <MKMapViewDelegate>
 13 @property (weak, nonatomic) IBOutlet MKMapView *mapView;
 14 @property (nonatomic, strong) CLGeocoder *geocoder;
 15 @end
 16
 17 @implementation MJViewController
 18
 19 - (CLGeocoder *)geocoder
 20 {
 21     if (!_geocoder) {
 22         self.geocoder = [[CLGeocoder alloc] init];
 23     }
 24     return _geocoder;
 25 }
 26
 27 - (void)viewDidLoad
 28 {
 29     [super viewDidLoad];
 30
 31     self.mapView.delegate = self;
 32
 33     NSString *address1 = @"北京";
 34     NSString *address2 = @"广州";
 35
 36     [self.geocoder geocodeAddressString:address1 completionHandler:^(NSArray *placemarks, NSError *error) {
 37         if (error) return;
 38
 39         CLPlacemark *fromPm = [placemarks firstObject];
 40
 41         [self.geocoder geocodeAddressString:address2 completionHandler:^(NSArray *placemarks, NSError *error) {
 42             if (error) return;
 43
 44             CLPlacemark *toPm = [placemarks firstObject];
 45
 46             [self addLineFrom:fromPm to:toPm];
 47         }];
 48     }];
 49
 50
 51 }
 52
 53 /**
 54  *  添加导航的线路
 55  *
 56  *  @param fromPm 起始位置
 57  *  @param toPm   结束位置
 58  */
 59 - (void)addLineFrom:(CLPlacemark *)fromPm to:(CLPlacemark *)toPm
 60 {
 61     // 1.添加2个大头针
 62     LsAnnotation *fromAnno = [[LsAnnotation alloc] init];
 63     fromAnno.coordinate = fromPm.location.coordinate;
 64     fromAnno.title = fromPm.name;
 65     [self.mapView addAnnotation:fromAnno];
 66
 67     LsAnnotation *toAnno = [[LsAnnotation alloc] init];
 68     toAnno.coordinate = toPm.location.coordinate;
 69     toAnno.title = toPm.name;
 70     [self.mapView addAnnotation:toAnno];
 71
 72     // 2.查找路线
 73
 74     // 方向请求
 75     MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
 76     // 设置起点
 77     MKPlacemark *sourcePm = [[MKPlacemark alloc] initWithPlacemark:fromPm];
 78     request.source = [[MKMapItem alloc] initWithPlacemark:sourcePm];
 79
 80     // 设置终点
 81     MKPlacemark *destinationPm = [[MKPlacemark alloc] initWithPlacemark:toPm];
 82     request.destination = [[MKMapItem alloc] initWithPlacemark:destinationPm];
 83
 84     // 方向对象
 85     MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
 86
 87     // 计算路线
 88     [directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
 89 //        NSLog(@"总共%lu条路线",   [response.routes count]);
 90
 91         // 遍历所有的路线
 92         for (MKRoute *route in response.routes) {
 93             // 添加路线遮盖
 94             [self.mapView addOverlay:route.polyline];
 95         }
 96     }];
 97 }
 98
 99 #pragma mark - MKMapViewDelegate
100 - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
101 {
102     MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
103     renderer.strokeColor = [UIColor redColor];
104     return renderer;
105 }
106 @end

时间: 2024-10-16 07:59:01

再MapView中添加路径的相关文章

AJAX跨域访问如何再服务器中添加过滤器

1.再工程文件中新建filter package com.TestFilter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import

简单东西-链接路径中添加随机数的作用

今天实现登陆的验证码生成功能,有一个"看不清"的链接,用于获取新的验证码,通过JS动态修正验证码的img元素的src属性,结果,验证码一直都是初始页面生成的那张图片,但是"看不清"的JS脚本已经执行过了.网上查资料才知道是浏览器缓存问题,解决办法是在请求路径中添加一个随机参数,迫使浏览器放弃缓存.重新去请求验证码. 原来随机数还有这个用途,以前也经常看到请求路径末尾添加一个参数Rand=Math.random()的代码,却从未关注这样处理的用意.简单知识,今天碰到了

Mac在PATH中永久添加路径

Mac系统的环境变量,加载顺序为: /etc/profile /etc/paths ~/.bash_profile ~/.bash_login ~/.profile ~/.bashrc /etc/profile和/etc/paths是系统级别的,系统启动就会加载,后面几个是当前用户级的环境变量.后面3个按照从前往后的顺序读取,如果~/.bash_profile文件存在,则后面的几个文件就会被忽略不读了,如果~/.bash_profile文件不存在,才会以此类推读取后面的文件.~/.bashrc没

ros项目 CMakeLists.txt中添加自己的库路径

原创博文,转载请标明出处:http://www.cnblogs.com/yongpan/p/6657400.html 在 ros 功能包中要使用第三方的动态库,将其放在系统默认库路径和使用绝对路径均不可取,这样的话可移植性较差,将该功能包移到其它电脑时要重新配置依赖库的路径,太麻烦了. 于是找到下面这个方法,解决了ROS功能包中添加库路径的问题. 注:此法针对 ros catkin编译. 在ROS功能包下的CMakeLists.txt 中添加 如下代码: link_directories( ${

Linux系统之在PATH中添加自己的路径

在PATH中添加自己的路径,有几种方法可以使用,本文主要介绍的是通过修改/etc/profile文件来实现: 第一步:通过命令打开profile文件 vim /etc/profile 在文件的最后添加上如下: PATH=$PATH:xxxxxxx; export PATH xxxxxx为自己需要添加的目录路径 第二步:通过输入下面命令来使修改即时生效,否则需要reboot source /etc/profile 通过以上两步修改,即可将自己的目录路径添加到PATH中

java.sql.SQLException: 不支持的字符集 (在类路径中添加 orai18n.jar): ZHS16GBK

在pom.xml文件中添加如下依赖: <!-- https://mvnrepository.com/artifact/cn.easyproject/orai18n --> <dependency> <groupId>cn.easyproject</groupId> <artifactId>orai18n</artifactId> <version>12.1.0.2.0</version> </depend

crontab中添加定时脚本不生效的原因

最近一段在检查服务器的定时脚本的时候发现了有部分服务器上的mysqldump定时脚本并没有被执行,因为在脚本中有生成日志所以就发现了问题.于是先去/var/log/cron中查看了下日志发现在相应的时候crond有执行相应的脚本,初步分析是是脚本的逻辑有问题于是就去看了下,并且执行了下发现脚本的逻辑是没有问题的,而且直接执行是没有问题的,后来又去/etc/crontab文件里去看了下 发现crontab中的环境变量不一样,但是脚本中有使用绝对路径,最后发现mysqldump中有使用allow-k

在开发中关于javaweb中的路径问题小结

转自http://blog.csdn.net/yinyuehepijiu/article/details/9136117 在javaweb项目中添加配置文件,满足连接数据库配置参数以及其他自定义参数存放,可自己写一个配置文件**.properties,把项目所需的自定义配置信息以名值对的形式写入文件.在项目工程目录下的WebRoot\WEB-INF\classes目录下新建一个conf文件夹专门存放配置文件,然后把**.properties配置文件放到conf中,部署时IDE会自动将其复制到相应

在ubuntu中添加新硬盘

在ubuntu中添加新硬盘 转载于 http://www.cnblogs.com/unipower/archive/2009/03/08/1406230.html 前言 安装新硬盘这种事情并不会经常,发生同样它也并不复杂.本文将向你说明如何在现有的Ubuntu系统下安装一个新硬盘,并为它设置好分区然后使用它.在动手之前,你需要先考虑下面三个关于新硬盘使用方面的问题: 该硬盘是否只会在Ubuntu下使用? 该硬盘是否要被Ubuntu和windows两类系统使用? 你打算如何分区,是全部空间作一个个