地图篇-03.展示地图

地图篇-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

运行效果图:

使用这个属性,系统会自动给你选择一个合适的范围.

 

好了,展示地图小节就到此为止了,大家如果觉得有什么问题或者哪里不足都可以告诉我.谢谢

 

posted on 2016-05-25 22:50  Xib'sStory  阅读(935)  评论(0编辑  收藏  举报

导航