iOS核心筆記—MapKit架構-導航

來源:互聯網
上載者:User

標籤:求導   struct   添加   init   sel   效果   for   when   lock   

1、導航簡介:

?瞭解:導航,簡單來說,就是根據使用者指定的位置,進行路線規劃;然後根據使用者在行走過程中,即時的給出指引提示。

1-1、iOS導航實現方案:
方案 詳細說明
方案一 將需要導航的位置傳遞給系統的地圖APP進行導航
方案二 發送網路請求到Apple伺服器/公司伺服器擷取導航資料,然後,手動繪製導航路線
方案三 利用第三方SDK實現導航功能(百度地圖)

?說明:通常如果需要手動繪製導航路線,都是向Apple伺服器發送請求、擷取導航資訊;此處,只對方案一、方案二做詳細介紹,方案三將單獨說明。

2、系統內建地圖APP導航:

?瞭解採用逆推法,實現使用Apple系統內建地圖進行導航;該方式導航關鍵在於:[MKMapItem openMapsWithItems:導航路線點 launchOptions:啟動參數]

2-1、詳細步驟:
步驟 詳細介紹 備忘
第一步 設定導航路線的起點、終點,將目標地址地理編碼成CLLPlacemark地標對象,根據CLLPlacemark對象建立MKPlacemark對象,MKPlacemark對象在地圖上代表每一個點、再根據MKPlacemark對象建立對應的模型,即:MKMapItem對象 MKMapItem
第二步 設定起點、終點模型數組,配置開啟系統地圖APP啟動參數 啟動地圖應用前相關準備工作
第三步 通過MKMapItem的openMapsWithItems:launchOptions:方法開啟系統內建地圖進行導航 MKMapItem類方法

?重要:通過地理編碼擷取目標位置的CLPlacemark對象,再根據CLPlacemark對象建立MKPlacemark對象;然後,根據MKPlacemark對象建立對應的資料模型對象MKMapItem對象,最後,將所有的導航路線的資料模型對象封裝成數組,通過MKMapItem對象的openMapsWithItems:launchOptions:類方法傳遞給系統內建地圖APP;最終,系統內建地圖APP根據傳入的資料模型對象完成導航操作。

2-2、補充說明:
  • 1、開啟系統地圖應用時,如果沒有設定啟動參數,使用者進入系統地圖之後需要一步一步自主擷取導航資訊。
  • 2、MKPlacemark繼承自CLPlacemark,所以,通過CLPlacemark對象可以建立一個MKPlacemark對象。
  • 3、通過MKMapItem的mapItemForCurrentLocation類方法可以直接擷取目前使用者所在位置對應的資料模型,但是,需要請求使用者定位授權,因為,牽涉到定位使用者當前所在位置。
  • 4、使用內建地圖APP進行導航的本質:是確定導航路線中要經過的點(CLLPlacemark - - -> MKPlacemark),再將地圖上導航所需要用到的地標對象(MKPlacemark)轉換成對應的模型(MKMapItem),再將所有的模型通過MKMapItem的openMapsWithItems:launchOptions:類方法傳遞給系統地圖APP,這樣就能藉助系統地圖對指定位置進行導航。
  • 5、使用系統地圖APP進行導航核心類:MKMapItem、MKPlacemark。
2-3、範例程式碼:
1.    // MARK: - 設定起點、終點
2. // 1. 將當前位置設定為起點模型
3. MKMapItem *beginItem = [MKMapItem mapItemForCurrentLocation];
4.
5. // 2. 設定終點
6. [self.geocoder geocodeAddressString:@"長沙" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
7. // 2.1 擷取地標對象
8. CLPlacemark *clPlacemark = [placemarks firstObject];
9.
10. // 2.2 根據CLPlacemark建立MKPlacemark
11. MKPlacemark *endPlacemark = [[MKPlacemark alloc] initWithPlacemark:clPlacemark];
12.
13. // 2.3 建立終點模型
14. MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endPlacemark];
15.
16. // MARK: - 使用MKMapItem開啟系統地圖進行導航
17. // 1. 起點、終點模型數組
18. NSArray *items = @[beginItem, endItem];
19.
20. // 2. 設定啟動參數
21. NSDictionary *dict = @{
22. MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
23. MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),
24. MKLaunchOptionsShowsTrafficKey : @(YES)
25. };
26.
27. // 3. 開啟系統地圖APP, 進行導航
28. [MKMapItem openMapsWithItems:items launchOptions:dict];
29. }];
3、手動繪製導航路線:

?瞭解:想要實現手動繪製導航路線,需要向Apple伺服器發送網路請求擷取導航路線;需要記住關鍵對象:導航對象 - - -> MKDirections

?重要:顯示在螢幕上的導航路線也是一個覆蓋層,在地圖上操作覆蓋層,其實操作的是覆蓋層的資料模型;刪除覆蓋層:在地圖上移除覆蓋層資料模型;添加覆蓋層:在地圖上添加覆蓋層資料模型。

3-1、詳細步驟:
步驟 詳細介紹 備忘
第一步 建立導航請求對象(MKDirectionsRequest),在該對象中儲存有本次導航的起點模型(MKMapItem)、終點模型(MKMapItem),MKDirectionsRequest對象的source、destination屬性專門用來儲存起點、終點模型 建立請求
第二步 通過導航請求對象建立導航對象(MKDirections) 建立導航對象
第三步 導航對象(MKDirections)調用calculateDirectionsWithCompletionHandler:方法開始向Apple伺服器發送請求、擷取導航資料資訊 擷取導航資料
第四步 從Apple伺服器擷取到導航資料之後開始解析資料(註:導航資料存放在響應體MKDirectionsResponse對象中),從response中便能擷取導航路線對象數組、遍曆該數組擷取導航路線對象(MKRoute)、將導航路線對象中的要顯示的渲染圖層對應的資料模型添加到mapView中 解析導航資料
第五步 實現返回要顯示在mapView上的渲染圖層代理方法,在該代理方法中建立渲染圖層(MKPolylineRenderer、MKCircleRenderer,具體渲染圖層由添加到mapView中的資料模型的類型決定;MKPolyline:折線資料模型,MKCircle:原型資料模型) 返回渲染圖層
3-2、詳細說明樣本圖:

?說明:本質:向Apple伺服器發送請求,擷取導航資料;擷取的導航資料實質是導航路線對象,將導航路線對象中的渲染圖層資料模型屬性添加到mapView;實現mapView的代理方法,在代理方法中建立渲染圖層、並設定相關屬性,系統自動將渲染圖層添加到mapView上面。

3-3、範例程式碼:
1.#import "ViewController.h"
2.#import <MapKit/MapKit.h>
3.
[email protected] ViewController () <MKMapViewDelegate>
5./** 地圖 */
[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;
7./** 地理編碼 */
[email protected] (strong, nonatomic) CLGeocoder *geocoder;
9./** 位置管理者對象 */
[email protected] (strong, nonatomic) CLLocationManager *mgr;
11.
[email protected]
13.
[email protected] ViewController
15.
16.- (void)viewDidLoad {
17. [super viewDidLoad];
18.
19. // MARK: - 請求授權
20. self.mgr = [CLLocationManager new];
21. if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
22. [self.mgr requestWhenInUseAuthorization];
23. }
24.
25. // MARK: - 設定代理
26. self.mapView.delegate = self;
27.}
28.
29.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
30. // MARK: - 開始導航
31. [self.geocoder geocodeAddressString:@"長沙" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
32. // 0. 地理編碼失敗, 返回
33. if (placemarks.count == 0 || error) {
34. NSLog(@"地理編碼失敗");
35. return ;
36. }
37.
38. // MARK: - 建立導航請求對象
39. MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
40.
41. // MARK: - 設定起點、終點模型
42. // 1. 起點模型, 使用該方式擷取當前點對應的資料模型 "需要請求使用者定位授權"
43. MKMapItem *beginItem = [MKMapItem mapItemForCurrentLocation];
44. request.source = beginItem;
45.
46. // 2. 設定終點
47. CLPlacemark *endCL = placemarks.firstObject;
48. MKPlacemark *endPL = [[MKPlacemark alloc] initWithPlacemark:endCL];
49. MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endPL];
50. request.destination = endItem;
51.
52. // 3. 根據MKDirectionsRequest對象, 建立導航對象
53. MKDirections *direction = [[MKDirections alloc] initWithRequest:request];
54.
55. // 4. 計算導航路線
56. [direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {
57.
58. if (error != nil) {
59. NSLog(@"導航失敗");
60. }
61. NSLog(@"%zd", response.routes.count);
62.
63. // 4.1. 遍曆導航路線對象數組, MKRoute : 導航路線對象
64. [response.routes enumerateObjectsUsingBlock:^(MKRoute * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
65. // 4.2 將導航路線對象中儲存的渲染圖層對應的資料模型添加到mapView中
66. [self.mapView addOverlay:obj.polyline];
67. }];
68. }];
69. }];
70.}
71.
72.#pragma mark - <MKMapViewDelegate>
73.- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
74. // 1. 建立折線渲染圖層
75. MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
76.
77. // 2. 設定折線渲染圖層相關屬性
78. renderer.lineWidth = 10; // 折線渲染圖層折線線寬
79. renderer.strokeColor = [UIColor greenColor]; // 折線渲染圖層折線顏色
80.
81. // 3. 返回折線渲染圖層
82. return renderer;
83.}
84.
85.#pragma mark - 懶載入
86.- (CLGeocoder *)geocoder{
87. if (_geocoder == nil) {
88. _geocoder = [[CLGeocoder alloc] init];
89. }
90. return _geocoder;
91.}
[email protected]
4、重要類:4-1、MKDirectionsResponse—響應體對象:
屬性名稱 作用
source 導航起點位置模型
destination 導航終點位置模型
routes 導航路線對象數組,數組中存放MKRoute對象
4-2、MKRoute—導航路線對象:
屬性名稱 作用
name 導航路線名稱
advisoryNotices 導航路線中注意、警告資訊
distance 導航路線長度(實際物理距離,單位:m)
polyline 導航路線渲染圖層幾何圖形資料模型(即:該資料模型對應的渲染圖層的形狀為折線,將來往mapView中添加該類型資料模型時,在代理方法中應當建立折線渲染圖層返回)
steps 多個行走步驟組成的數組(例如“前方路口左轉”,“保持直行”等等, MKRouteStep 對象)

?注意:MKRoute是一整條路,MKRouteStep是這條長路中的每一節。

4-3、MKRouteStep—導航步驟對象:
屬性名稱 作用
instructions 步驟說明(例如“前方路口左轉”,“保持直行”等)
transportType 交通方式(駕車,步行等)
polyline 路線對應的在地圖上的幾何線路資料模型(由很多點組成,可繪製在地圖上)
5、導航渲染圖層效果:5-1、折線渲染圖層效果:

範例程式碼:

1.#import "ViewController.h"
2.#import <MapKit/MapKit.h>
3.
[email protected] ViewController () <MKMapViewDelegate>
5./** 地圖 */
[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;
7./** 地理編碼 */
[email protected] (strong, nonatomic) CLGeocoder *geocoder;
9./** 位置管理者對象 */
[email protected] (strong, nonatomic) CLLocationManager *mgr;
[email protected]
12.
[email protected] ViewController
14.
15.- (void)viewDidLoad {
16. [super viewDidLoad];
17.
18. // MARK: - 設定代理
19. self.mapView.delegate = self;
20.
21. // MARK: - 請求授權
22. self.mgr = [[CLLocationManager alloc] init];
23. if ([self.mgr respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
24. [self.mgr requestWhenInUseAuthorization];
25. }
26.}
27.
28.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
29. // MARK: - 建立導航請求對象
30. MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
31.
32. // 1. 設定起點資料模型
33. MKMapItem *beginItem = [MKMapItem mapItemForCurrentLocation];
34.
35. // 2. 設定終點資料模型
36. [self.geocoder geocodeAddressString:@"耒陽" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
37. // 3. 建立MKPlacemark對象
38. CLPlacemark *endCL = placemarks.firstObject;
39. MKPlacemark *endPL = [[MKPlacemark alloc] initWithPlacemark:endCL];
40.
41. // 4. 建立終點資料模型
42. MKMapItem *endItem = [[MKMapItem alloc] initWithPlacemark:endPL];
43.
44. // 5. 設定為請求對象
45. request.source = beginItem;
46. request.destination = endItem;
47.
48. // MARK: - 建立導航對象
49. MKDirections *direcion = [[MKDirections alloc] initWithRequest:request];
50.
51. // 1. 計算導航資料
52. [direcion calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse * _Nullable response, NSError * _Nullable error) {
53. // 2. 防錯處理
54. if (placemarks.count == 0 || error) {
55. NSLog(@"請求導航錯誤");
56. return ;
57. }
58.
59. // 3. 遍曆導航路線對象數組, 將折線渲染圖層資料模型添加到mapView
60. [response.routes enumerateObjectsUsingBlock:^(MKRoute * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
61. // 4. 將渲染層資料模型添加mapView
62. [self.mapView addOverlay:obj.polyline];
63. }];
64. }];
65. }];
66.}
67.
68.#pragma mark - <MKMapViewDelegate>
69.- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
70. // 1. 建立折線渲染圖層
71. MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
72.
73. // 2. 設定相關屬性
74. renderer.lineWidth = 10;
75. renderer.strokeColor = [UIColor redColor];
76.
77. // 3. 返回折線渲染圖層
78. return renderer;
79.}
80.
81.#pragma mark - 地理編碼
82.- (CLGeocoder *)geocoder{
83. if (_geocoder == nil) {
84. _geocoder = [[CLGeocoder alloc] init];
85. }
86. return _geocoder;
87.}
[email protected]

效果樣本圖

5-2、圓形渲染圖層效果:

範例程式碼

1.#import "ViewController.h"
2.#import <MapKit/MapKit.h>
3.
[email protected] ViewController () <MKMapViewDelegate>
5./** 地圖 */
[email protected] (weak, nonatomic) IBOutlet MKMapView *mapView;
7.
[email protected]
9.
[email protected] ViewController
11.
12.- (void)viewDidLoad {
13. [super viewDidLoad];
14.
15. // MARK: - 設定mapView的代理
16. self.mapView.delegate = self;
17.}
18.
19.- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
20. // MARK: - 添加圓形渲染圖層模型
21. // 1. 圓形渲染圖層中心點
22. CLLocationCoordinate2D center = CLLocationCoordinate2DMake(40, 116);
23.
24. // 2. 建立圓形渲染圖層資料模型
25. MKCircle *circle = [MKCircle circleWithCenterCoordinate:center radius:1000000];
26.
27. // 3. 添加到mapView
28. [self.mapView addOverlay:circle];
29.}
30.
31.#pragma mark - <MKMapViewDelegate>
32./**
33. 當往mapView中添加資料模型時, 便會調用該方法返回對應的渲染圖層
34.
35. @param mapView 地圖
36. @param overlay 渲染圖層模型
37. @return 渲染圖層
38. */
39.- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
40. // 1. 建立圓形渲染圖層
41. MKCircleRenderer *renderer = [[MKCircleRenderer alloc] initWithOverlay:overlay];
42.
43. // 2. 設定屬性
44. renderer.fillColor = [UIColor greenColor];
45. renderer.alpha = 0.5;
46.
47. // 3. 返回圓形渲染圖層
48. return renderer;
49.}
[email protected]

效果樣本圖

iOS核心筆記—MapKit架構-導航

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.