标签:求导 struct 添加 init sel 效果 for when lock
?了解:导航,简单来说,就是根据用户指定的位置,进行路线规划;然后根据用户在行走过程中,实时的给出指引提示。
| 方案 | 详细说明 | 
|---|---|
| 方案一 | 将需要导航的位置传递给系统的地图APP进行导航 | 
| 方案二 | 发送网络请求到Apple服务器/公司服务器获取导航数据,然后,手动绘制导航路线 | 
| 方案三 | 利用第三方SDK实现导航功能(百度地图) | 
?说明:通常如果需要手动绘制导航路线,都是向Apple服务器发送请求、获取导航信息;此处,只对方案一、方案二做详细介绍,方案三将单独说明。
?了解:采用逆推法,实现使用Apple系统自带地图进行导航;该方式导航关键在于:[MKMapItem openMapsWithItems:导航路线点 launchOptions:启动参数]。
| 步骤 | 详细介绍 | 备注 | 
|---|---|---|
| 第一步 | 设置导航路线的起点、终点,将目标地址地理编码成CLLPlacemark地标对象,根据CLLPlacemark对象创建MKPlacemark对象,MKPlacemark对象在地图上代表每一个点、再根据MKPlacemark对象创建对应的模型,即:MKMapItem对象 | MKMapItem | 
| 第二步 | 设置起点、终点模型数组,配置打开系统地图APP启动参数 | 启动地图应用前相关准备工作 | 
| 第三步 | 通过MKMapItem的 openMapsWithItems:launchOptions:方法打开系统自带地图进行导航 | MKMapItem类方法 | 
?重要:通过地理编码获取目标位置的CLPlacemark对象,再根据CLPlacemark对象创建MKPlacemark对象;然后,根据MKPlacemark对象创建对应的数据模型对象MKMapItem对象,最后,将所有的导航路线的数据模型对象包装成数组,通过MKMapItem对象的openMapsWithItems:launchOptions:类方法传递给系统自带地图APP;最终,系统自带地图APP根据传入的数据模型对象完成导航操作。
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.    }];
?了解:想要实现手动绘制导航路线,需要向Apple服务器发送网络请求获取导航路线;需要记住关键对象:导航对象- - ->MKDirections。
?重要:显示在屏幕上的导航路线也是一个覆盖层,在地图上操作覆盖层,其实操作的是覆盖层的数据模型;删除覆盖层:在地图上移除覆盖层数据模型;添加覆盖层:在地图上添加覆盖层数据模型。
| 步骤 | 详细介绍 | 备注 | 
|---|---|---|
| 第一步 | 创建导航请求对象(MKDirectionsRequest),在该对象中保存有本次导航的起点模型(MKMapItem)、终点模型(MKMapItem),MKDirectionsRequest对象的source、destination属性专门用来保存起点、终点模型 | 创建请求 | 
| 第二步 | 通过导航请求对象创建导航对象(MKDirections) | 创建导航对象 | 
| 第三步 | 导航对象(MKDirections)调用calculateDirectionsWithCompletionHandler:方法开始向Apple服务器发送请求、获取导航数据信息 | 获取导航数据 | 
| 第四步 | 从Apple服务器获取到导航数据之后开始解析数据(注:导航数据存放在响应体MKDirectionsResponse对象中),从response中便能获取导航路线对象数组、遍历该数组获取导航路线对象(MKRoute)、将导航路线对象中的要显示的渲染图层对应的数据模型添加到mapView中 | 解析导航数据 | 
| 第五步 | 实现返回要显示在mapView上的渲染图层代理方法,在该代理方法中创建渲染图层(MKPolylineRenderer、MKCircleRenderer,具体渲染图层由添加到mapView中的数据模型的类型决定;MKPolyline:折线数据模型,MKCircle:原型数据模型) | 返回渲染图层 | 
?说明:本质:向Apple服务器发送请求,获取导航数据;获取的导航数据实质是导航路线对象,将导航路线对象中的渲染图层数据模型属性添加到mapView;实现mapView的代理方法,在代理方法中创建渲染图层、并设置相关属性,系统自动将渲染图层添加到mapView上面。
1.#import "ViewController.h"
2.#import <MapKit/MapKit.h>
3.
4.@interface ViewController () <MKMapViewDelegate>
5./** 地图 */
6.@property (weak, nonatomic) IBOutlet MKMapView *mapView;
7./** 地理编码 */
8.@property (strong, nonatomic) CLGeocoder *geocoder;
9./** 位置管理者对象 */
10.@property (strong, nonatomic) CLLocationManager *mgr;
11.
12.@end
13.
14.@implementation 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.}
92.@end
| 属性名 | 作用 | 
|---|---|
| source | 导航起点位置模型 | 
| destination | 导航终点位置模型 | 
| routes | 导航路线对象数组,数组中存放MKRoute对象 | 
| 属性名 | 作用 | 
|---|---|
| name | 导航路线名称 | 
| advisoryNotices | 导航路线中注意、警告信息 | 
| distance | 导航路线长度(实际物理距离,单位:m) | 
| polyline | 导航路线渲染图层几何形状数据模型(即:该数据模型对应的渲染图层的形状为折线,将来往mapView中添加该类型数据模型时,在代理方法中应当创建折线渲染图层返回) | 
| steps | 多个行走步骤组成的数组(例如“前方路口左转”,“保持直行”等等, MKRouteStep 对象) | 
?注意:MKRoute是一整条路,MKRouteStep是这条长路中的每一节。
| 属性名 | 作用 | 
|---|---|
| instructions | 步骤说明(例如“前方路口左转”,“保持直行”等) | 
| transportType | 交通方式(驾车,步行等) | 
| polyline | 路线对应的在地图上的几何线路数据模型(由很多点组成,可绘制在地图上) | 
示例代码:
1.#import "ViewController.h"
2.#import <MapKit/MapKit.h>
3.
4.@interface ViewController () <MKMapViewDelegate>
5./** 地图 */
6.@property (weak, nonatomic) IBOutlet MKMapView *mapView;
7./** 地理编码 */
8.@property (strong, nonatomic) CLGeocoder *geocoder;
9./** 位置管理者对象 */
10.@property (strong, nonatomic) CLLocationManager *mgr;
11.@end
12.
13.@implementation 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.}
88.@end
效果示例图:
示例代码:
1.#import "ViewController.h"
2.#import <MapKit/MapKit.h>
3.
4.@interface ViewController () <MKMapViewDelegate>
5./** 地图 */
6.@property (weak, nonatomic) IBOutlet MKMapView *mapView;
7.
8.@end
9.
10.@implementation 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.}
50.@end
效果示例图:
标签:求导 struct 添加 init sel 效果 for when lock
原文地址:http://www.cnblogs.com/leilifengixng/p/6367469.html