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.1viewDidLoad 中的加載
1 #import "ViewController.h" 2 #import "MapKit/MapKit.h" 3 #import "MyPointAnnotation.h" 4 #import "MyAnnotationView.h" 5 6 @interface ViewController (){ 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)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)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:placeMark.name 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 * _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:place.name 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 #import4 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 #import3 #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 )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