打開系統自帶地圖的導航,必需要告訴自帶的地圖起始點和目的地,自帶的地圖又不會本身知道你想怎麼走。程序員
咱們的思路大體上是:獲取咱們想要導航的起始點和目的地,經過反地址編碼得到兩個地址的地理信息(地圖總歸不能本身根據漢字就知道該怎麼作的吧),將地理信息封裝或則不封裝(假設咱們並不知道要不要封裝,作以前誰都不會,這是確定的)傳遞給自帶地圖(傳遞的方法如今假設還不知道,後面會有講到)。函數
首先搭建咱們界面,這個步驟繁瑣而簡單,對於老程序員或許不屑於爲之,可是能把簡單的事情作好就是不簡單,再怎麼熟悉你能保證每次作都不會出錯嗎,因此必定要認真對待每一步。編碼
必需要輸入起始地和目的地吧,那就拖兩個textView進去。再拖一個導航開始的Button進去,將這三個控件連線到相應的控制器。有時,爲了迎合主流地圖軟件傻瓜式的操做,咱們在其實地點的輸入框右側加一個設置"起始點"爲"當前位置"的按鈕。atom
造成的界面和代碼以下:spa
下面是拖線以後的代碼:code
@property (weak, nonatomic) IBOutlet UITextField *startField;//其實地點的輸入框 @property (weak, nonatomic) IBOutlet UITextField *endField;//目的地的輸入框 - (IBAction)current;//(右側「current「按鈕操做)獲取當前位置 - (IBAction)startNavigation;//」開始導航「按鈕操做
假設沒有這個解析器,你告訴我該怎麼作,沒思路是嗎,因此我告訴你,咱們須要這個解析器。對象
有了界面以後,第二部就是解析出"漢字"中的"地理信息",只有這些特殊的"地理信息",地圖纔可以識別,傳給它漢字它要是能識別,就沒人作導航了。blog
不知道你不知不知道,從"漢字"獲取地理信息,叫作"反地理編碼",固然還有"地理編碼"(知道地理信息,其實就是經度和緯度兩個值,通過編碼器獲取地名等一些關於編碼出的地點的其餘信息。如需更多信息,請參照其餘人的文章).string
咱們提到編碼器,其實就是這個:it
@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 }
那如今編碼器也有了,就能夠獲取地理信息了。
這段比較長,可能難理解,可是代碼很順暢,好好看。別問我爲何很差好一句一句寫,累了,手疼
下面是代碼,無碼無真相:
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