思路分析
打开系统自带地图的导航,必须要告诉自带的地图起始点和目的地,自带的地图又不会自己知道你想怎么走。
我们的思路大致上是:获取我们想要导航的起始点和目的地,通过反地址编码获得两个地址的地理信息(地图总归不能自己根据汉字就知道该怎么做的吧),将地理信息封装或则不封装(假设我们并不知道要不要封装,做之前谁都不会,这是肯定的)传递给自带地图(传递的方法现在假设还不知道,后面会有讲到)。
开始我们的编码吧!
1.搭建界面
首先搭建我们界面,这个步骤繁琐而简单,对于老程序员或许不屑于为之,但是能把简单的事情做好就是不简单,再怎么熟悉你能保证每次做都不会出错吗,所以一定要认真对待每一步。
必须要输入起始地和目的地吧,那就拖两个textView进去。再拖一个导航开始的Button进去,将这三个控件连线到相应的控制器。有时,为了迎合主流地图软件傻瓜式的操作,我们在其实地点的输入框右侧加一个设置"起始点"为"当前位置"的按钮。
形成的界面和代码如下:
下面是拖线之后的代码:
@property (weak, nonatomic) IBOutlet UITextField *startField;//其实地点的输入框
@property (weak, nonatomic) IBOutlet UITextField *endField;//目的地的输入框
- (IBAction)current;//(右侧“current“按钮操作)获取当前位置
- (IBAction)startNavigation;//”开始导航“按钮操作
2. 创建解析器
假设没有这个解析器,你告诉我该怎么做,没思路是吗,所以我告诉你,我们需要这个解析器。
有了界面之后,第二部就是解析出"汉字"中的"地理信息",只有这些特殊的"地理信息",地图才能够识别,传给它汉字它要是能识别,就没人做导航了。
不知道你不知不知道,从"汉字"获取地理信息,叫做"反地理编码",当然还有"地理编码"(知道地理信息,其实就是经度和纬度两个值,经过编码器获取地名等一些关于编码出的地点的其他信息。如需更多信息,请参照其他人的文章).
我们提到编码器,其实就是这个:
@property (strong, nonatomic) CLGeocoder *geocoder;
为了保持它不被销毁,设置为strong。
我们让它成为懒加载对象
1 - (CLGeocoder *)geocoder
2 {
3 if (_geocoder == nil) {
4 self.geocoder = [[CLGeocoder alloc] init];
5 }
6 return _geocoder;
7 }
3. 获取地理信息,打开地图
那现在编码器也有了,就可以获取地理信息了。
这段比较长,可能难理解,但是代码很顺畅,好好看。别问我为什么不好好一句一句写,累了,手疼
下面是代码,无码无真相:
1 - (IBAction)startNavigation {//这个函数就是我们"开始导航"的操作函数
2 [self.geocoder geocodeAddressString:self.endField.text completionHandler:^(NSArray *placemarks, NSError *error) {//编码器拿到string类型的地名进行反编码,完了之后调用completionhandler块代码,传入反编码的结果NSArray和错误信息
3 if (error) return;//如果发编码有错误,后面也就不用进行了,直接返回
4
5 CLPlacemark *placemark = [placemarks firstObject];//能够到这里说明没有错误,那我们取出众多结果中最有可信度的(也就是第一个,人们习惯把最好的放在前面),先不要管CLPlacemark是什么,想知道的话百度下就知道了。
6 //下面我们封装获得的地理结果,看得出我们至获取了目的地的地理信息,那是因为我们默认使用当前位置,也就是你输入了起始地我们也没用,你想用可以根据代码自己编写
7 MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation];//有简单的方法把当前位置封装到MKMapItem中
8 MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithPlacemark:placemark]];//地理信息"placemark"封装到"MKPlacemark"中,"MKPlacemark"被封装到"MKMapItem"中,还真是封装了好几层,没办法,mapView只识别"MKMapItem"
9 //下面建立一个可变字典,选择你要对自带地图所做的操作属性,讲这个字典传给地图就行了,还真是神奇
10 NSMutableDictionary *options = [NSMutableDictionary dictionary];
11 options[MKLaunchOptionsDirectionsModeKey] = MKLaunchOptionsDirectionsModeDriving;//自驾模式
12 options[MKLaunchOptionsShowsTrafficKey] = @YES;//开启导航
13 [MKMapItem openMapsWithItems:@[currentLocation, toLocation] launchOptions:options];
14 }];//withItems看得出地图只是别MKMapItem对象。最后只用了一句话打开地图,他妈的只用了一句话。
15 }
我的运行截图
完整代码
其他的代码文件压根没动过,只在ViewController和main.storyboard里面进行编码和拖拽了
// // ViewController.m // 预习-05-苹果自带地图 #import "ViewController.h" #import <CoreLocation/CoreLocation.h> #import <MapKit/MapKit.h> @interface ViewController () @property (strong, nonatomic) CLGeocoder *geocoder; @property (weak, nonatomic) IBOutlet UITextField *startField; @property (weak, nonatomic) IBOutlet UITextField *endField; - (IBAction)current; - (IBAction)startNavigation; @end @implementation ViewController - (CLGeocoder *)geocoder { if (_geocoder == nil) { self.geocoder = [[CLGeocoder alloc] init]; } return _geocoder; } - (void)viewDidLoad { [super viewDidLoad]; } - (IBAction)current { } - (IBAction)startNavigation { [self.geocoder geocodeAddressString:self.endField.text completionHandler:^(NSArray *placemarks, NSError *error) { if (error) return; CLPlacemark *placemark = [placemarks firstObject]; MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation]; MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithPlacemark:placemark]]; NSMutableDictionary *options = [NSMutableDictionary dictionary]; options[MKLaunchOptionsDirectionsModeKey] = MKLaunchOptionsDirectionsModeDriving; options[MKLaunchOptionsShowsTrafficKey] = @YES; [MKMapItem openMapsWithItems:@[currentLocation, toLocation] launchOptions:options]; }]; } @end
不服者请留言 !!!