要實現地圖、導航功能,每每須要先熟悉定位功能,在iOS中經過Core Location框架進行定位操做。Core Location自⾝能夠單獨使用,和地圖開發框架MapKit徹底是獨立的,可是每每地圖開發要配合定位框架使用。在Core Location 中主要包含了定位、地理編碼(包括反編碼)功能。git
Core Location的主要功能:app
1.獲取經緯度框架
2.地理編碼(根據給定的地名,得到具體的位置信息(如經緯度、地址的全稱等))
3.反地理編碼(根據給定的經緯度,得到具體的位置信息)異步
導入MapKit框架ide
#import <MapKit/MapKit.h>
簽定MKMapViewDelegate協議 ,添加成員變量動畫
@interface ViewController () <MKMapViewDelegate> @property (nonatomic, strong) CLLocationManager* locationManager; @end
設置地圖的樣式編碼
MKMapTypeStandard = 0, 平面地圖 MKMapTypeSatellite :衛星雲圖 (中圖) MKMapTypeHybrid :混合模式(普通地圖覆蓋於衛星雲圖之上 ) MKMapTypeSatelliteFlyover: 3D立體衛星 (iOS9.0) MKMapTypeHybridFlyover: 3D立體混合 (iOS9.0) self.mapView.mapType = MKMapTypeStandard;
是否顯示用戶位置 atom
self.mapView.showsUserLocation = YES;
受權定位用戶的位置,須要在info.plist文件中添加(如下二選一,兩個都添加默認使用NSLocationWhenInUseUsageDescription):spa
if ([CLLocationManager instanceMethodForSelector:@selector(requestWhenInUseAuthorization)]) { [self.locationManager requestWhenInUseAuthorization]; } }
定位的精確度rest
kCLLocationAccuracyBestForNavigation // 最適合導航 kCLLocationAccuracyBest; // 最好的 kCLLocationAccuracyNearestTenMeters; // 10m kCLLocationAccuracyHundredMeters; // 100m kCLLocationAccuracyKilometer; // 1000m kCLLocationAccuracyThreeKilometers; // 3000m // 精確度越高, 越耗電, 定位時間越長 _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
每一個多少米定位一次
_locationManager.distanceFilter = 10;
地理編碼(根據給定的地名,得到具體的位置信息(如經緯度、地址的全稱等))
對應方法
建立編碼對象
@property (strong, nonatomic) CLGeocoder *geocoder;
建立一個block做爲參數傳遞的方式
@property (strong, nonatomic) void(^geocodeComplatHandle)(NSString *name);
在手勢方法裏面調用[self geocoder:coordinate2D]
方法傳遞一個經緯度進去
- (void)geocoder:(CLLocationCoordinate2D)coordinate2D { // 建立一個經緯度位置 CLLocation CLLocation *location = [[CLLocation alloc] initWithLatitude:coordinate2D.latitude longitude:coordinate2D.longitude]; // 一、經過經緯度獲取對應的地理位置,查詢位置是一個異步操做 [self.geocoder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { CLPlacemark *placemark = [placemarks lastObject]; NSLog(@"%@ %@ %@",placemark.name, placemark.thoroughfare,placemark.subThoroughfare); // 將地理位置名稱顯示在標註視圖上 if (self.geocodeComplatHandle) { self.geocodeComplatHandle(placemark.name,placemark.thoroughfare); } }]; }
對應方法
反地理編碼(根據給定的經緯度,得到具體的位置信息)
- (IBAction)search:(id)sender { [self.geocoder geocodeAddressString:self.searchText.text completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { CLPlacemark *placemark = placemarks[0]; //建立並添加一個標註視圖到mapView上 MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init]; annotation.coordinate = placemark.location.coordinate; //將標註添加到地圖上 [self.mapView addAnnotation:annotation]; }]; }
在iOS6之後,蘋果再也不使用蘋果地圖,⽽是使用蘋果⾃己的地圖。咱們使用Core Location來獲取⽤戶的位置信息,MapKit則是⽤來顯⽰具體的信息。其核心是MKMapView類的使用,咱們能夠設置地圖顯示方式,控制地圖,能夠在地圖上添加標註。
MKMapViewDelegate協議方法
#pragma mark - <MKMapViewDelegate> // 地圖加載完成 - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView { NSLog(@"%s %f, %f",__func__, mapView.userLocation.coordinate.longitude, mapView.userLocation.coordinate.latitude); } // 用戶位置更新後調用 - (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { //設置中心點 CLLocationCoordinate2D center = userLocation.location.coordinate; // 設置跨度 MKCoordinateSpan span = {0.01,0.01}; // 設置地圖顯示的範圍 [self.mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES]; NSLog(@"用戶位置發生改變"); }
使用長按手勢添加標註,建立一個長按手勢,添加到mapView上面
UILongPressGestureRecognizer *longGest = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longGestAction:)]; [self.mapView addGestureRecognizer:longGest];
手勢方法實現
- (void)longGestAction:(UILongPressGestureRecognizer *)longGest { // 獲取觸摸點所在地圖上的CGPoint座標 CGPoint point = [longGest locationInView:self.mapView]; // 將地圖所在觸摸點的座標 CGPoint 轉爲對應的經緯度 CLLocationCoordinate2D CLLocationCoordinate2D coordinate2D = [self.mapView convertPoint:point toCoordinateFromView:self.mapView]; if (longGest.state == UIGestureRecognizerStateBegan) { // 建立並添加一個標註視圖到mapView上 MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init]; annotation.title = @"XXXX"; annotation.coordinate = coordinate2D; annotation.subtitle = [NSString stringWithFormat:@"%f, %f",annotation.coordinate.latitude, annotation.coordinate.longitude]; [self setGeocodeComplatHandle:^(NSString *locationName1,NSString *locationName2) { annotation.title = loationName1; annotation.subtitle = locationName2; }]; // 地理位置編碼方法 [self geocoder:coordinate2D]; // 將標註添加到地圖上 [self.mapView addAnnotation:annotation]; } }
3.1 步驟:
1.⾃定義實現MKAnnotation的類並從新coordinate,title,subtitle屬性。
2.實現MKMapViewDelegate的- mapView:viewForAnnotation: 方法。
自定義標註視圖功能實現:
用戶位置發生改變後調用
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation { CLLocationCoordinate2D center = userLocation.location.coordinate; MKCoordinateSpan span = {0.05,0.05}; [mapView setRegion:MKCoordinateRegionMake(center, span) animated:YES]; }
添加了標註視圖後調用
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray<MKAnnotationView *> *)views { NSLog(@"添加了標註視圖後調用"); }
添加標註視圖時調用,這裏能夠自定義標註視圖
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { NSLog(@"viewForAnnotation"); // 判斷是不是用戶當前的位置標註 if (![annotation isKindOfClass:[MKPointAnnotation class]]) { return nil; } //設置重用標示符 static NSString *identifer = @"annotation"; //先從重用的隊列中找 MKAnnotationView *annatationView = [mapView dequeueReusableAnnotationViewWithIdentifier:identifer];
大頭針樣式
// MKPinAnnotationView *annatationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifer];
是否顯示輔助標註視圖
annatationView.canShowCallout = YES;
設置大頭針的顏色,前提是爲MKPinAnnotationView類型
annatationView.pinTintColor = [UIColor orangeColor];
設置大頭針出現的動畫,前提是爲MKPinAnnotationView類型
annatationView.animatesDrop = YES;
使用圖片做爲標註
annatationView.image = [UIImage imageNamed:@"icon"];
是否能夠拖拽
annatationView.draggable = YES;
設置標註視圖的偏移
annatationView.centerOffset = CGPointMake(0, -25);
設置輔助視圖的偏移
annatationView.calloutOffset = CGPointMake(0, -10); UIButton *leftView = [UIButton buttonWithType:UIButtonTypeCustom]; [leftView setImage:[UIImage imageNamed:@"頭像"] forState:UIControlStateNormal]; leftView.tag = 100; leftView.frame = CGRectMake(0, 0, 50, 50);
設置左邊的輔助視圖
annatationView.leftCalloutAccessoryView = leftView;
設置右邊的輔助視圖
annatationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeContactAdd];
點擊標註視圖時調用
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view { NSLog(@"didSelectAnnotationView"); }
點擊左右輔助視圖時調用
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control { NSLog(@"%@",control); }
地圖開始加載時調用
- (void)mapViewWillStartLoadingMap:(MKMapView *)mapView { NSLog(@"地圖開始加載時調用"); }
地圖加載完成時調用
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView { NSLog(@"地圖加載完成時調用"); }
地圖加載失敗時調用
- (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error { NSLog(@"地圖加載失敗時調用"); }
地圖顯示的範圍將要發生改變時調用
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated { NSLog(@"地圖顯示的範圍將要發生改變時調用"); }
地圖顯示的範圍改變後調用
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated { NSLog(@"地圖顯示的範圍改變後調用"); }
定位用戶的位置失敗
- (void)mapView:(MKMapView *)mapView didFailToLocateUserWithError:(NSError *)error { NSLog(@"定位用戶的位置失敗"); }
標註視圖拖拽後調用
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState fromOldState:(MKAnnotationViewDragState)oldState { /** 拖拽的狀態 MKAnnotationViewDragStateNone = 0, 沒有拖拽 MKAnnotationViewDragStateStarting, 開始拖拽 MKAnnotationViewDragStateDragging, 正在拖拽 MKAnnotationViewDragStateCanceling, 取消拖拽 MKAnnotationViewDragStateEnding 結束拖拽 **/ NSLog(@"didChangeDragState"); }