1. 创建之前的准备工作
1.1 在Info.plist文件中添加下面两句话
NSLocationAlwaysUsageDescription —> 确定定位吗?亲
//请求的授权,除了可以在APP打开时允许定位服务,也可以在APP进入后台仍然可以使用定位服务(永久) --> 与上边一个可以二选一
[_locationManager requestAlwaysAuthorization];
NSLocationWhenInUseUsageDescripyion —>需要定位吗?
//此方法请求的授权,仅限于用户在打开使用APP时允许使用系统的定位服务(在应用使用期间)
[_locationManager requestWhenInUseAuthorization];
1.2 导入库文件 MapKit.framework 和 CoreLocation.framework
2. 工程创建说明 ---> 使用系统自带的MKPointAnnotation、MKPinAnnotationView 及自定义 MKPointAnnotation、MKPinAnnotationView
以下是ViewController.m 文件
2.1 viewDidLoad 中的加载
1 #import "ViewController.h"
2 #import "MapKit/MapKit.h"
3 #import "MyPointAnnotation.h"
4 #import "MyAnnotationView.h"
5
6 @interface ViewController ()<MKMapViewDelegate> {
7
8 MKMapView *_mapView; //地图对象
9 UILabel *_userLocationLable; //查看用户坐标
10 }
11
12 @end
13
14 @implementation ViewController
15
16 - (void)viewDidLoad {
17 [super viewDidLoad];
18
19 //调用创建地图视图的方法
20 [self createMapView];
21 //调用创建大头针的方法
22 [self createAnnotations];
23 //调用这个方法调用所有的覆盖层的方法
24 [self overLay];
25 //调用创建UI的方法
26 [self createUI];
27 }
28
29 @end
2.2 创建地图视图的方法
1 //创建地图视图的方法
2 - (void)createMapView {
3 //创建地图对象
4 _mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
5 //设置map的类型 或地图模式
6 _mapView.mapType = MKMapTypeStandard;
7 /*
8 MKMapTypeStandard = 0, 纸张地图 标准地图
9 MKMapTypeSatellite, 纯卫星地图
10 MKMapTypeHybrid, 混合式地图 描述的卫星图
11 */
12 //设置map的初始位置
13 //创建地理坐标2D 需要经度和纬度 如:经度:120.366486 纬度:36.083743
14 CLLocationCoordinate2D location = CLLocationCoordinate2DMake(36.083743, 120.366486);
15 //起始时 锁定一个矩形为1000 X 1000米的方位 ,坐标点location
16 _mapView.region = MKCoordinateRegionMakeWithDistance(location, 1000, 1000);
17 //设置地图能否放大缩小
18 _mapView.zoomEnabled = YES;
19 //设置地图能否滚动
20 _mapView.scrollEnabled = YES;
21 //设置显示用户的位置 先判断是否开始了定位服务
22 if ([CLLocationManager locationServicesEnabled] == YES) {
23 //显示用户的位置
24 _mapView.showsUserLocation = YES;
25 //设置用户的基本跟踪状态
26 [_mapView setUserTrackingMode:MKUserTrackingModeFollowWithHeading animated:YES];
27
28 /*
29 MKUserTrackingModeNone = 0, 不尾随 一般不设
30 MKUserTrackingModeFollow, 尾随用户位置,地图保存正向(北方向)
31 MKUserTrackingModeFollowWithHeading 随着地图旋转而尾随(地图方向和设备方向同步)
32 */
33 }
34 //设置代理 需遵守MKMapViewDelegate代理协议
35 _mapView.delegate = self;
36 //将地图加入到self.view上
37 [self.view addSubview:_mapView];
38 }
39
40 #pragma mark - 地图协议中的方法 -
41 - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
42
43 //这里判断必须要加,这个方法在刷新时会将用户的位置也会传到这个方法里,所以需要判断,如果不是大头针就是用户坐标点(蓝点),如果是蓝点(用户坐标点) 直接返回nil
44 if ([annotation isKindOfClass:[MKPointAnnotation class]] == NO) {
45 return nil;
46 }
47
48 //调用系统的方法
49 // MKPinAnnotationView *annotationView = [self systemMethodWithMapView:mapView andAnnotation:annotation];
50
51 //调用自定义的方法
52 MKPinAnnotationView *annotationView = [self customMethodWithMapView:mapView andAnnotation:annotation];
53
54 return annotationView;
55 }
56
57 //自定义的方法
58 - (MKPinAnnotationView *)customMethodWithMapView:(MKMapView *)mapView andAnnotation:(MKPointAnnotation *)annotation {
59 MyAnnotationView *annotationView = (MyAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"CustomAnnotationView"];
60
61 if (annotationView == nil) {
62
63
64 annotationView = [[MyAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"CustomAnnotationView"];
65
66 }else {
67
68 annotationView.annotation = annotation;
69 }
70
71
72
73 return annotationView;
74 }
75
76
77 //系统方法
78 - (MKPinAnnotationView *)systemMethodWithMapView:(MKMapView *)mapView andAnnotation:(MKPointAnnotation *)annotation {
79
80 // 类似于tableview的复用机制那个方法
81 MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"AnnotationView"];
82 if (annotationView == nil) {
83 //如果从队列取 没有的话,需要创建新的大头针视图
84 annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"AnnotationView"];
85 //设置大头针的色彩,默认是红色,还有绿色和紫色(了解)
86 annotationView.pinColor = MKPinAnnotationColorPurple;
87 //设置允许显示气泡(重要)
88 annotationView.canShowCallout = YES;
89 //设置下坠动画 (从上往下掉下来) 默认为NO
90 annotationView.animatesDrop = YES;
91 //设置是佛可以拖拽
92 annotationView.draggable = YES;
93
94 }else {
95
96 //如果有空闲,拿队列里空闲的view 然后显示大头针
97 annotationView.annotation = annotation;
98
99 }
100 return annotationView;
101 }
2.3 创建大头针的方法
1 //创建大头针的方法
2 - (void)createAnnotations {
3 //创建大头针1
4 MKPointAnnotation *annotation1 = [[MKPointAnnotation alloc] init];
5 //设置title
6 annotation1.title = @"不知道是哪";
7 //设置子title
8 annotation1.subtitle = @"真不知道是哪儿";
9 //设置大头针的经纬度坐标
10 annotation1.coordinate = CLLocationCoordinate2DMake(-39.89, -79.88);
11 //把大头针1加入到地图上
12 [_mapView addAnnotation:annotation1];
13 //创建大头针2
14 MKPointAnnotation *annotation2 = [[MKPointAnnotation alloc] init];
15 annotation2.title = @"南半球";
16 annotation2.subtitle = @"真是南半球";
17 annotation2.coordinate = CLLocationCoordinate2DMake(-80.89, 156.456);
18 [_mapView addAnnotation:annotation2];
19 //自定义方式创建大头针3
20 MyPointAnnotation *annotation3 = [[MyPointAnnotation alloc] initWithCoorDinate:CLLocationCoordinate2DMake(40.5, -88.7) title:@"第一个位置" subTitle:@"这里风景优美" information:@"这里是国家级旅游景点"];
21 //自定义方式创建大头针4
22 MyPointAnnotation *annotation4 = [[MyPointAnnotation alloc] initWithCoorDinate:CLLocationCoordinate2DMake(37.68, -96.54) title:@"第二个位置" subTitle:@"这里有点冷" information:@"世界冰展所在地"];
23 //将大头针3和4一块加入到地图上 用addAnnotations
24 [_mapView addAnnotations:@[annotation3,annotation4]];
25
26 //将地图滚动到大头针3的位置
27 _mapView.centerCoordinate = annotation1.coordinate;
28
29 }
2.4 这个方法调用所有的覆盖层的方法
1 //这个方法调用所有的覆盖层的方法
2 - (void)overLay {
3
4 //调用绘制线的方法
5 [self pathOverLay];
6
7 //调用多边形图层的方法
8 [self polyOverlay];
9
10 //调用绘制圆的图层的方法
11 [self circleOverlay];
12
13 }
14
15 //绘制圆的图层的方法
16 - (void)circleOverlay {
17 //圆图层和annotation一样需要添加到地图上,每个图层绘制都需要实现管理图层方法
18 CLLocationCoordinate2D centerLocation = CLLocationCoordinate2DMake(37.68, -96.54);
19 //绘制圆
20 MKCircle *circleOverlay = [MKCircle circleWithCenterCoordinate:centerLocation radius:100000];
21 //添加到地图上
22 [_mapView addOverlay:circleOverlay];
23
24 }
25
26 //多边形图层的方法
27 - (void)polyOverlay {
28 //设置多边形的角的坐标,记住一定要首尾相连
29
30 CLLocationCoordinate2D ploycoords[5] = {
31 CLLocationCoordinate2DMake(35.443, -77.876),
32 CLLocationCoordinate2DMake(36.553, -77.976),
33 CLLocationCoordinate2DMake(35.553, -79.567),
34 CLLocationCoordinate2DMake(34.443, -79.567),
35 CLLocationCoordinate2DMake(35.443, -77.876)
36
37
38 };
39
40 MKPolygon *polygonOverlay = [MKPolygon polygonWithCoordinates:ploycoords count:5];
41 //添加到地图上
42 [_mapView addOverlay:polygonOverlay];
43 }
44
45 //绘制线的方法
46 - (void)pathOverLay {
47 CLLocationCoordinate2D pathCoords[6] = {
48
49 CLLocationCoordinate2DMake(33.123, -77.456),
50 CLLocationCoordinate2DMake(34.123, -78.456),
51 CLLocationCoordinate2DMake(32.123, -79.456),
52 CLLocationCoordinate2DMake(36.123, -71.456),
53 CLLocationCoordinate2DMake(35.123, -70.456),
54 CLLocationCoordinate2DMake(36.123, 73.456)
55
56 };
57
58 //创建图层
59 MKPolyline *pathOverlay = [MKPolyline polylineWithCoordinates:pathCoords count:6];
60 //添加到地图上
61 [_mapView addOverlay:pathOverlay];
62
63
64 }
65
66 //管理图层视图
67 - (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
68
69 if ([overlay isKindOfClass:[MKPolyline class]] == YES) {
70 MKPolylineRenderer *line = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
71 //线的宽度
72 line.lineWidth = 2;
73 //设置线的颜色
74 line.strokeColor = [UIColor blueColor];
75
76 return line;
77
78 }else if ([overlay isKindOfClass:[MKPolygon class]] == YES) {
79
80 MKPolygonRenderer *poly = [[MKPolygonRenderer alloc] initWithOverlay:overlay];
81 //设置线宽
82 poly.lineWidth = 1;
83 //设置边缘颜色
84 poly.strokeColor = [UIColor greenColor];
85 //设置填充颜色
86 poly.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.5];
87
88 return poly;
89
90 }else if ([overlay isKindOfClass:[MKCircle class]] == YES) {
91
92 //创建圆视图 所有的视图都是overlay添加到构造方法参数
93 MKCircleRenderer *circle = [[MKCircleRenderer alloc] initWithOverlay:overlay];
94 //设置边缘宽度
95 circle.lineWidth = 1;
96 //设置边缘颜色
97 circle.strokeColor = [UIColor redColor];
98 //设置填充颜色 透明度0.4
99 circle.fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.4];
100
101 return circle;
102 }
103
104 return nil;
105 }
2.5 创建UI的方法 在创建该方法之前需要在AppDelegate.m 文件中将ViewController包装成导航控制器
1 //创建UI的方法
2 - (void)createUI {
3
4 _userLocationLable = [[UILabel alloc] initWithFrame:CGRectMake(0, 64, 320, 80)];
5 [self.view addSubview:_userLocationLable];
6 //创建BarButtonItem 这个是用户定位(跟随),参数放入一个MapView类型的地图对象
7 MKUserTrackingBarButtonItem *item = [[MKUserTrackingBarButtonItem alloc] initWithMapView:_mapView];
8 //设置导航左边的BarButtonItem
9 self.navigationItem.leftBarButtonItem = item;
10
11 UIButton *hotSearchButton = [UIButton buttonWithType:UIButtonTypeCustom];
12 hotSearchButton.frame = CGRectMake(0, 64, 100, 40);
13 [hotSearchButton setTitle:@"热点搜索" forState:UIControlStateNormal];
14
15 [hotSearchButton addTarget:self action:@selector(hotSeatch) forControlEvents:UIControlEventTouchUpInside];
16
17
18 [hotSearchButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
19
20 [self.view addSubview:hotSearchButton];
21
22
23 UIButton *keywordSearchButton = [UIButton buttonWithType:UIButtonTypeCustom];
24
25 keywordSearchButton.frame = CGRectMake(100, 64, 100, 40);
26
27 [keywordSearchButton setTitle:@"关键字搜索" forState:UIControlStateNormal];
28
29 [keywordSearchButton addTarget:self action:@selector(keywordSearch) forControlEvents:UIControlEventTouchUpInside];
30 [keywordSearchButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
31
32 [self.view addSubview:keywordSearchButton];
33
34 //添加一个长按的手势 用长按的手势添加大头针
35 UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
36 longPress.minimumPressDuration = 1;
37 //长按手势加入到地图
38 [_mapView addGestureRecognizer:longPress];
39 }
40
41 //长按手势执行的方法
42 - (void)longPress:(UILongPressGestureRecognizer *)longPress {
43 //注:一定别忘了判断
44 //判断长按手势状态 如果是开始的状态,就执行判断题
45 if (longPress.state == UIGestureRecognizerStateBegan) {
46 //在地图上找到CGPoint坐标(屏幕坐标)
47 CGPoint point = [longPress locationInView:_mapView];
48 //屏幕坐标转成经纬度坐标
49 CLLocationCoordinate2D coordinate = [_mapView convertPoint:point toCoordinateFromView:_mapView];
50 //创建大头针
51
52 MyPointAnnotation *annotation = [[MyPointAnnotation alloc] initWithCoorDinate:coordinate title:@"手势加入" subTitle:@"长按手势" information:@"长按手势信息"];
53
54
55 //加入到地图上
56 [_mapView addAnnotation:annotation];
57
58 }
59
60
61 }
62
63
64 - (void)hotSeatch {
65 //创建本地搜索请求
66 MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
67 //设置搜索热点词(自然语言)
68 request.naturalLanguageQuery = @"学校";
69 //设置搜索范围,以某个原点为中心,向外扩展一段经纬度距离范围
70 CLLocationCoordinate2D origionpoint = CLLocationCoordinate2DMake(36.08397, 120.37126);
71 //设置经纬度跨越范围
72 MKCoordinateSpan span = MKCoordinateSpanMake(0.3, 0.3);
73 //设置经纬度搜索区域
74 MKCoordinateRegion region = MKCoordinateRegionMake(origionpoint, span);
75 //将区域赋值给搜索请求对象中的region属性中
76 request.region = region;
77 //将地图移动到该区域
78 [_mapView setRegion:region];
79
80 //创建本地搜索对象
81 MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];
82 //开启搜索
83 [search startWithCompletionHandler:^(MKLocalSearchResponse * _Nullable response, NSError * _Nullable error) {
84
85 if (error == nil) {
86
87 //搜索成功
88 //获取搜索结果
89 NSArray *arrResult = response.mapItems;
90
91 for (MKMapItem *item in arrResult) {
92
93 //先取出地图目的坐标对象(标记)
94 MKPlacemark *placeMark = item.placemark;
95 /*
96 地标里存放的经纬度,以及位置的地理信息说明,如名字、街道等等
97 */
98 //创建大头针
99 MyPointAnnotation *annotation = [[MyPointAnnotation alloc] initWithCoorDinate:placeMark.location.coordinate title: subTitle:placeMark.locality information:placeMark.locality];
100
101 //加入到地图中
102 [_mapView addAnnotation:annotation];
103 }
104
105
106 }else {
107 NSLog(@"搜索失败");
108
109 }
110
111 }];
112
113 }
114
115 //关键字搜索
116 - (void)keywordSearch {
117 //创建地理编码
118 CLGeocoder *geocoder = [[CLGeocoder alloc] init];
119 //正向地理编码
120 [geocoder geocodeAddressString:@"青岛科技大学" completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {
121
122 if (error == nil) {
123 //解析地理位置成功
124 //成功后遍历数组
125 for (CLPlacemark *place in placemarks) {
126
127 //创建大头针
128
129 MyPointAnnotation *annotation = [[MyPointAnnotation alloc] initWithCoorDinate:place.location.coordinate title: subTitle:place.locality information:place.locality];
130 //将大头针加入到地图
131 [_mapView addAnnotation:annotation];
132
133 }
134
135 }else {
136
137 NSLog(@"正向地理编码解析失败");
138 }
139
140
141 }];
142
143 }
144
145
146 //完成更新用户定位
147 - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
148
149
150 _userLocationLable.text = [NSString stringWithFormat:@"用户位置: %.5f, %.5f",userLocation.coordinate.latitude, userLocation.coordinate.longitude];
151 NSLog(@"%@",_userLocationLable.text);
152
153 }
3. 自定义 MyPointAnnotation 工程如下:
1 MyPointAnnotation.h文件
2
3 #import <MapKit/MapKit.h>
4
5 @interface MyPointAnnotation : MKPointAnnotation
6
7 /** 大头针信息 */
8 @property(nonatomic, copy) NSString *information;
9
10 //构造方法
11 - (id)initWithCoorDinate:(CLLocationCoordinate2D)coordinate title:(NSString *)title subTitle:(NSString *)subTitle information:(NSString *)information;
12
13 @end
14
15 MyPointAnnotation.m文件
16
17 #import "MyPointAnnotation.h"
18
19 @implementation MyPointAnnotation
20
21 - (id)initWithCoorDinate:(CLLocationCoordinate2D)coordinate title:(NSString *)title subTitle:(NSString *)subTitle information:(NSString *)information {
22
23 if (self = [super init]) {
24 //标题
25 self.title = title;
26 //子标题
27 self.subtitle = subTitle;
28 //坐标
29 self.coordinate = coordinate;
30 //信息
31 self.information = information;
32 }
33 return self;
34 }
35
36 @end
4. 自定义 MyAnnotationView工程如下:
1 MyAnnotationView.h文件
2 #import <MapKit/MapKit.h>
3 #import "MyPointAnnotation.h" //导入自定义的大头针
4 @interface MyAnnotationView : MKPinAnnotationView {
5
6 MyPointAnnotation *myPointAnnotation;
7
8 }
9
10 //静态图片需要继承这个
11 //@interface MyAnnotationView : MKAnnotationView {
12 // MyPointAnnotation *myPointAnnotation;
13 //}
14
15 @end
16
17
18 MyAnnotationView.m文件
19 #import "MyAnnotationView.h"
20
21 @implementation MyAnnotationView
22
23 - (instancetype)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
24 if (self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]) {
25 //保存参数-传过来的大头针
26 myPointAnnotation = annotation;
27
28 //创建图片
29 UIImage *image = [UIImage imageNamed:@"pink"];
30
31 //这种方式只适合静态图片 ,不适合动态和拖拽动态功能,它们有冲突 需要更改一下.h文件中的继承
32 //这种方式继承MKAnnotationView 否则没有效果
33 // NSData *imageData = UIImagePNGRepresentation(image);
34 // //处理imageData 比例5
35 // image = [UIImage imageWithData:imageData scale:5];
36 // //修改当前视图的大小
37 // self.frame = CGRectMake(0, 0, 40, 40);
38 // //设置图片
39 // self.image = image;
40 // //设置填充模式 按比例填满
41 // self.contentMode = UIViewContentModeScaleToFill;
42
43
44 UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(-15, -5, 45, 45)];
45 imageView.image = image;
46 [self addSubview:imageView];
47
48 //允许气泡弹出
49 self.canShowCallout = YES;
50 //拖拽
51 self.draggable = YES;
52 //下坠动画
53 self.animatesDrop = YES;
54
55
56 UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
57 [leftButton addTarget:self action:@selector(leftButton) forControlEvents:UIControlEventTouchUpInside];
58 //设置左边访问view
59 self.leftCalloutAccessoryView = leftButton;
60
61 UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
62 [rightButton addTarget:self action:@selector(rightButton) forControlEvents:UIControlEventTouchUpInside];
63 //设置右边访问view
64 self.rightCalloutAccessoryView = rightButton;
65
66 }
67 return self;
68 }
69
70
71 - (void)leftButton {
72 NSLog(@"leftButton:%@",myPointAnnotation.title);
73 }
74
75 - (void)rightButton {
76 NSLog(@"rightButton:%@",myPointAnnotation.information);
77 }
78
79 @end