地圖篇-03.展示地圖 這一小節是地圖展示,在這一小節要接觸到一個框架:MapKit 1.展示地圖 展示地圖特別簡單,就是調用系統的地圖,有兩種方式,直接上代碼 第一種方式: 導入頭文件 #import <MapKit/MapKit.h> 然後輸入以下代碼: 運行可見: 細心的朋友能開到地圖右下角有 ...
地圖篇-03.展示地圖
這一小節是地圖展示,在這一小節要接觸到一個框架:MapKit
1.展示地圖
展示地圖特別簡單,就是調用系統的地圖,有兩種方式,直接上代碼
第一種方式:
導入頭文件
#import <MapKit/MapKit.h>
然後輸入以下代碼:
1 // 1.代碼展示地圖 2 MKMapView *mapView = [[MKMapView alloc] initWithFrame:self.view.bounds]; 3 4 [self.view addSubview:mapView];
運行可見:
細心的朋友能開到地圖右下角有一個高德地圖,這是蘋果自帶的框架使用的數據是高德的,但是在國外的話就不會顯示這個,可以去試試改IP顯示.
第二種方法:
通過storyboard來創建
自動佈局前面說過了,這裡就不講了.
註意在使用storyboard拖入mapView的時候,需要導入框架和頭文件
運行得到同樣的效果.
2.用戶位置(藍色小圓點)
前面已經講到了用戶位置,這裡不多講,直接上代碼
1 // 2 // ViewController.m 3 // 03.展示地圖 4 // 5 // Created by admin on 16/5/25. 6 // Copyright © 2016年 KXZDJ. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import <MapKit/MapKit.h> 11 12 @interface ViewController () 13 @property (weak, nonatomic) IBOutlet MKMapView *mapView; 14 //這裡沒有導入CLLocation頭文件的原因是MapKit包含了 15 @property (nonatomic, strong) CLLocationManager *mgr; 16 17 @end 18 19 @implementation ViewController 20 21 -(CLLocationManager *)mgr { 22 if (!_mgr) { 23 _mgr = [[CLLocationManager alloc] init]; 24 //這裡不需要用到代理方法,所以不設置代理 25 } 26 return _mgr; 27 } 28 29 - (void)viewDidLoad { 30 [super viewDidLoad]; 31 //獲取用戶位置 32 self.mapView.showsUserLocation = YES; 33 //請求用戶授權,然後在info.plist文件裡面配置欄位NSLocationAlwaysUsageDescription 34 //這裡我就不判斷了,直接添加always欄位. 35 [self.mgr requestAlwaysAuthorization]; 36 37 } 38 39 - (void)didReceiveMemoryWarning { 40 [super didReceiveMemoryWarning]; 41 // Dispose of any resources that can be recreated. 42 } 43 44 @end
運行效果:
現在就能看到地圖上的藍色小圓點了,但是:
點擊小圓點彈出的提示框只顯示了一個current location,能不能顯示當前位置呢?肯定可以的啦,這裡就要用到地理編碼的知識了.
因為我們能獲取到用戶位置,就可以通過反地理編碼,把他轉換成當前位置.通過mapView的代理方法,顯示出來.
3.用戶詳細地址
代碼:
1 // 2 // ViewController.m 3 // 03.展示地圖 4 // 5 // Created by admin on 16/5/25. 6 // Copyright © 2016年 KXZDJ. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import <MapKit/MapKit.h> 11 12 @interface ViewController ()<MKMapViewDelegate> 13 @property (weak, nonatomic) IBOutlet MKMapView *mapView; 14 //這裡沒有導入CLLocation頭文件的原因是MapKit包含了 15 @property (nonatomic, strong) CLLocationManager *mgr; 16 17 @end 18 19 @implementation ViewController 20 21 -(CLLocationManager *)mgr { 22 if (!_mgr) { 23 _mgr = [[CLLocationManager alloc] init]; 24 //這裡不需要用到代理方法,所以不設置代理 25 } 26 return _mgr; 27 } 28 29 - (void)viewDidLoad { 30 [super viewDidLoad]; 31 //獲取用戶位置 32 self.mapView.showsUserLocation = YES; 33 //請求用戶授權,然後在info.plist文件裡面配置欄位NSLocationAlwaysUsageDescription 34 //這裡我就不判斷了,直接添加always欄位. 35 [self.mgr requestAlwaysAuthorization]; 36 //設置代理 37 self.mapView.delegate = self; 38 } 39 40 - (void)didReceiveMemoryWarning { 41 [super didReceiveMemoryWarning]; 42 // Dispose of any resources that can be recreated. 43 } 44 /** 45 * 當用戶位置更新的時候調用 46 * 47 * @param mapView 當前地圖 48 * @param userLocation 用戶位置 49 */ 50 -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { 51 //反地理編碼 52 CLGeocoder *reverseGeo = [[CLGeocoder alloc] init]; 53 //MKUserLocation-userLocation的屬性 54 /* 55 // 如果用戶的位置正在更新,返回YES. 56 @property (readonly, nonatomic, getter=isUpdating) BOOL updating; 57 58 // 如果MKMapView.showsUserLocation=NO或者用戶的位置尚未確定,返回nil. 59 @property (readonly, nonatomic, nullable) CLLocation *location; 60 61 // 如果不適用MKUserTrackingModeFollowWithHeading返回nil; 62 @property (readonly, nonatomic, nullable) CLHeading *heading NS_AVAILABLE(10_9, 5_0); 63 64 // 描述用戶當前位置的文本. 65 @property (nonatomic, copy, nullable) NSString *title; 66 67 // 描述用戶當前位置的詳細信息. 68 @property (nonatomic, copy, nullable) NSString *subtitle; 69 */ 70 [reverseGeo reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { 71 //判斷,如果返回的地標為空,或者error存在的時候 72 if (placemarks.count == 0 || error) { 73 NSLog(@"地理編碼失敗"); 74 return; 75 } 76 77 78 79 //根據userLocation.location進行反地理編碼獲得的地址只有一個(地理編碼小節中有講) 80 CLPlacemark *clp = [placemarks firstObject]; 81 //設置用戶當前位置的地址 82 userLocation.title = clp.name; 83 //設置用戶當前位置的詳細信息 84 userLocation.subtitle = @"那小子真帥...";//這裡可以列印街道,門牌號等等,這裡舉例. 85 86 87 }]; 88 89 } 90 91 @end
運行效果圖:
還好沒有打臉.- -!
4.地圖顯示範圍(經緯度跨度)
上面的地圖中,顯示了整個亞洲,但是我們平時使用的時候肯定想他自己定位在我們所在的城市,現在我想要改變一下這個跨度,有招!
mapView有個方法:設置區域範圍
self.mapView setRegion:(MKCoordinateRegion)
他需要一個MKCoordinateRegion類型的參數,看不懂?沒事,command+左鍵點進去,會看到如下圖:
一個結構體,裡面兩個參數,一個CLLocationCoordinate類型的,這個我們前面講過,坐標嘛,經緯度,所以這裡的center就是把用戶的經緯度用來當中心點.另外一個MKCoordinateSpan類型的,不知道?再點進去:
又是一個結構體,裡面也有兩個參數,首先,span:範圍,寬度的意思.latitudeDelta是緯度的跨度,longitudeDelta是經度的跨度.
大概瞭解了之後,上代碼:
1 // 2 // ViewController.m 3 // 03.展示地圖 4 // 5 // Created by admin on 16/5/25. 6 // Copyright © 2016年 KXZDJ. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import <MapKit/MapKit.h> 11 12 @interface ViewController ()<MKMapViewDelegate> 13 @property (weak, nonatomic) IBOutlet MKMapView *mapView; 14 //這裡沒有導入CLLocation頭文件的原因是MapKit包含了 15 @property (nonatomic, strong) CLLocationManager *mgr; 16 17 @end 18 19 @implementation ViewController 20 21 -(CLLocationManager *)mgr { 22 if (!_mgr) { 23 _mgr = [[CLLocationManager alloc] init]; 24 //這裡不需要用到代理方法,所以不設置代理 25 } 26 return _mgr; 27 } 28 29 - (void)viewDidLoad { 30 [super viewDidLoad]; 31 //獲取用戶位置 32 self.mapView.showsUserLocation = YES; 33 //請求用戶授權,然後在info.plist文件裡面配置欄位NSLocationAlwaysUsageDescription 34 //這裡我就不判斷了,直接添加always欄位. 35 [self.mgr requestAlwaysAuthorization]; 36 //設置代理 37 self.mapView.delegate = self; 38 39 //中心點 40 CLLocationCoordinate2D center = CLLocationCoordinate2DMake(30.67, 104.06); 41 //跨度 42 MKCoordinateSpan span = MKCoordinateSpanMake(1.0, 1.0); 43 //範圍 44 MKCoordinateRegion region = MKCoordinateRegionMake(center, span); 45 46 //地圖範圍 47 [self.mapView setRegion:region]; 48 49 } 50 51 - (void)didReceiveMemoryWarning { 52 [super didReceiveMemoryWarning]; 53 // Dispose of any resources that can be recreated. 54 } 55 /** 56 * 當用戶位置更新的時候調用 57 * 58 * @param mapView 當前地圖 59 * @param userLocation 用戶位置 60 */ 61 -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { 62 //反地理編碼 63 CLGeocoder *reverseGeo = [[CLGeocoder alloc] init]; 64 //MKUserLocation-userLocation的屬性 65 /* 66 // 如果用戶的位置正在更新,返回YES. 67 @property (readonly, nonatomic, getter=isUpdating) BOOL updating; 68 69 // 如果MKMapView.showsUserLocation=NO或者用戶的位置尚未確定,返回nil. 70 @property (readonly, nonatomic, nullable) CLLocation *location; 71 72 // 如果不適用MKUserTrackingModeFollowWithHeading返回nil; 73 @property (readonly, nonatomic, nullable) CLHeading *heading NS_AVAILABLE(10_9, 5_0); 74 75 // 描述用戶當前位置的文本. 76 @property (nonatomic, copy, nullable) NSString *title; 77 78 // 描述用戶當前位置的詳細信息. 79 @property (nonatomic, copy, nullable) NSString *subtitle; 80 */ 81 [reverseGeo reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { 82 //判斷,如果返回的地標為空,或者error存在的時候 83 if (placemarks.count == 0 || error) { 84 NSLog(@"地理編碼失敗"); 85 return; 86 } 87 88 89 90 //根據userLocation.location進行反地理編碼獲得的地址只有一個(地理編碼小節中有講) 91 CLPlacemark *clp = [placemarks firstObject]; 92 //設置用戶當前位置的地址 93 userLocation.title = clp.name; 94 //設置用戶當前位置的詳細信息 95 userLocation.subtitle = @"那小子真帥...";//這裡可以列印街道,門牌號等等,這裡舉例. 96 97 98 }]; 99 100 } 101 102 @end
運行效果如下:
在上面代碼中第42行,我們不知道這個範圍應該是多少,不用急,有兩個代理方法能帶我們裝X帶我們飛.
代碼:
1 /** 2 * 地圖的範圍已經改變的時候調用 3 */ 4 -(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { 5 //緯度的跨度 6 CLLocationDegrees latitudeDelta = mapView.region.span.latitudeDelta; 7 //經度的跨度 8 CLLocationDegrees longitudeDelta = mapView.region.span.longitudeDelta; 9 10 NSLog(@"緯度的跨度:%f,經度的跨度:%f",latitudeDelta,longitudeDelta); 11 } 12 /** 13 * 地圖的範圍將要改變的時候調用 14 */ 15 -(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated { 16 17 }
這兩個方法中能獲取到當前地圖的跨度,在模擬器上按住option鍵然後左鍵上下滑動,會看到列印如下:
可以自己試一下.
但是這種方法有點麻煩,要獲取坐標等一系列操作,下麵介紹一種方法,利用mapView的一個屬性userTrackingMode
代碼:
1 // 2 // ViewController.m 3 // 03.展示地圖 4 // 5 // Created by admin on 16/5/25. 6 // Copyright © 2016年 KXZDJ. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 #import <MapKit/MapKit.h> 11 12 @interface ViewController ()<MKMapViewDelegate> 13 @property (weak, nonatomic) IBOutlet MKMapView *mapView; 14 //這裡沒有導入CLLocation頭文件的原因是MapKit包含了 15 @property (nonatomic, strong) CLLocationManager *mgr; 16 17 @end 18 19 @implementation ViewController 20 21 -(CLLocationManager *)mgr { 22 if (!_mgr) { 23 _mgr = [[CLLocationManager alloc] init]; 24 //這裡不需要用到代理方法,所以不設置代理 25 } 26 return _mgr; 27 } 28 29 - (void)viewDidLoad { 30 [super viewDidLoad]; 31 //獲取用戶位置 32 self.mapView.showsUserLocation = YES; 33 //請求用戶授權,然後在info.plist文件裡面配置欄位NSLocationAlwaysUsageDescription 34 //這裡我就不判斷了,直接添加always欄位. 35 [self.mgr requestAlwaysAuthorization]; 36 //設置代理 37 self.mapView.delegate = self; 38 39 40 41 42 //跟蹤用戶位置(系統會自動給你設置一個比較合適的範圍) 43 self.mapView.userTrackingMode = MKUserTrackingModeFollow; 44 45 //中心點 46 // CLLocationCoordinate2D center = CLLocationCoordinate2DMake(30.67, 104.06); 47 // //跨度 48 // MKCoordinateSpan span = MKCoordinateSpanMake(1.0, 1.0); 49 // //範圍 50 // MKCoordinateRegion region = MKCoordinateRegionMake(center, span); 51 // 52 // //地圖範圍 53 // [self.mapView setRegion:region]; 54 55 } 56 57 - (void)didReceiveMemoryWarning { 58 [super didReceiveMemoryWarning]; 59 // Dispose of any resources that can be recreated. 60 } 61 /** 62 * 當用戶位置更新的時候調用 63 * 64 * @param mapView 當前地圖 65 * @param userLocation 用戶位置 66 */ 67 -(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { 68 //反地理編碼 69 CLGeocoder *reverseGeo = [[CLGeocoder alloc] init]; 70 //MKUserLocation-userLocation的屬性 71 /* 72 // 如果用戶的位置正在更新,返回YES. 73 @property (readonly, nonatomic, getter=isUpdating) BOOL updating; 74 75 // 如果MKMapView.showsUserLocation=NO或者用戶的位置尚未確定,返回nil. 76 @property (readonly, nonatomic, nullable) CLLocation *location; 77 78 // 如果不適用MKUserTrackingModeFollowWithHeading返回nil; 79 @property (readonly, nonatomic, nullable) CLHeading *heading NS_AVAILABLE(10_9, 5_0); 80 81 // 描述用戶當前位置的文本. 82 @property (nonatomic, copy, nullable) NSString *title; 83 84 // 描述用戶當前位置的詳細信息. 85 @property (nonatomic, copy, nullable) NSString *subtitle; 86 */ 87 [reverseGeo reverseGeocodeLocation:userLocation.location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { 88 //判斷,如果返回的地標為空,或者error存在的時候 89 if (placemarks.count == 0 || error) { 90 NSLog(@"地理編碼失敗"); 91 return; 92 } 93 94 95 96 //根據userLocation.location進行反地理編碼獲得的地址只有一個(地理編碼小節中有講) 97 CLPlacemark *clp = [placemarks firstObject]; 98 //設置用戶當前位置的地址 99 userLocation.title = clp.name; 100 //設置用戶當前位置的詳細信息 101 userLocation.subtitle = @"那小子真帥...";//這裡可以列印街道,門牌號等等,這裡舉例. 102 103 104 }]; 105 106 } 107 108 /** 109 * 地圖的範圍已經改變的時候調用 110 */ 111 -(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { 112 //緯度的跨度 113 CLLocationDegrees latitudeDelta = mapView.region.span.latitudeDelta; 114 //經度的跨度 115 CLLocationDegrees longitudeDelta = mapView.region.span.longitudeDelta; 116 117 NSLog(@"緯度的跨度:%f,經度的跨度:%f",latitudeDelta,longitudeDelta); 118 } 119 /** 120 * 地圖的範圍將要改變的時候調用 121 */ 122 -(void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated { 123 124 } 125 @end
運行效果圖:
使用這個屬性,系統會自動給你選擇一個合適的範圍.
好了,展示地圖小節就到此為止了,大家如果覺得有什麼問題或者哪裡不足都可以告訴我.謝謝