要實現地圖、導航功能,往須要先熟悉定位功能,在iOS中經過Core Location框架進⾏定位操做。Core Location⾃身能夠單獨使用,和地圖開發框架MapKit徹底是獨立的,可是往地圖開發要配合定位框架使用。在Core Location 中主要包含了定位、地理編碼(包括反編碼)功能。git
Core Location的主要功能:
1.獲取經緯度
2.地理編碼(根據給定的地名,得到具體的位置信息(如經緯度、地址的全 稱等))
3.反地利編碼(根據給定的經緯度,得到具體的位置信息)github
各個類的做用: CLLocation:用於表示位置信息,包含地理座標、海拔等信息,包含在CoreLoaction框架中。app
MKUserLocation:一個特殊的大頭針,表示用戶當前位置。框架
CLPlacemark:定位框架中地標類,封裝了詳細的地理信息。異步
MKPlacemark:相似於CLPlacemark,只是它在MapKit框架中,能夠根據CLPlacemark建立MKPlacemark。ide
##一、定位的基本使用動畫
導入MapKit框架,添加成員變量,簽定MKMapViewDelegate協議 這裏的MKMapView是使用故事板方式建立,在故事板裏面連線設置的協議代理編碼
#import "ViewController.h" #import <MapKit/MapKit.h> @interface ViewController ()<MKMapViewDelegate> @property (weak, nonatomic) IBOutlet MKMapView *mapView; @property (strong, nonatomic) CLLocationManager *locationManager; @end
設置地圖的樣式atom
/** MKMapTypeStandard = 0, 平面地圖 MKMapTypeSatellite, 衛星地圖 MKMapTypeHybrid, 混合地圖 MKMapTypeSatelliteFlyover NS_ENUM_AVAILABLE(10_11, 9_0), MKMapTypeHybridFlyover**/ self.mapView.mapType = MKMapTypeStandard;
是否顯示用戶位置spa
self.mapView.showsUserLocation = YES;
因爲目前蘋果的iOS系統最新版本爲9,蘋果自iOS8上之後若是要使用定位服務,受權定位用戶的位置,須要在info.plist文件中添加(如下二選一,兩個都添加默認使用NSLocationWhenInUseUsageDescription):
NSLocationWhenInUseUsageDescription
容許在前臺使用時獲取GPS的描述NSLocationAlwaysUsageDescription
容許永遠可獲取GPS的描述判斷當前設備版本大於iOS8之後的話執行裏面的方法
if ([UIDevice currentDevice].systemVersion.floatValue >=8.0) { //持續受權 [locationManager requestAlwaysAuthorization]; //當用戶使用的時候受權 [locationManager requestWhenInUseAuthorization]; }
或者使用這種方式,判斷是否存在這個方法,若是存在就執行,沒有的話就忽略
if ([CLLocationManager instanceMethodForSelector:@selector(requestWhenInUseAuthorization)]) { [self.locationManager requestWhenInUseAuthorization]; }
初始化locationManger管理器對象
_locationManager = [[CLLocationManager alloc] init];
設置定位的精確度 kCLLocationAccuracyNearestTenMeters
精確到10米 kCLLocationAccuracyHundredMeters
精確到100米kCLLocationAccuracyKilometer
精確到1000米 kCLLocationAccuracyThreeKilometers
精確到3000米 kCLLocationAccuracyBest
設備使用電池供電時最高的精度 kCLLocationAccuracyBestForNavigation
導航狀況下最高的精度,通常有外接電源時才能使用
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
多遠距離更新位置
_locationManager.distanceFilter = 10;
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]; }
##二、地圖添加標註視圖
在這裏咱們使用長按手勢添加標註
建立一個長按手勢,並添加到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 *a,NSString *b) { annotation.title = a; annotation.subtitle = b; }]; //地理位置編碼方法 [self geocoder:coordinate2D]; //四、將標註添加到地圖上 [self.mapView addAnnotation:annotation]; } }
##三、地理位置編碼
添加一個標註,經過點擊位置的經緯度得到標註位置的信息...
建立編碼對象
@property (strong, nonatomic) CLGeocoder *geocoder;
建立一個block做爲參數傳遞的方式
@property (strong, nonatomic) void(^geocodeComplatHandle)(NSString *, NSString *);
在手勢方法裏面調用[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]; }]; }
##五、自定義標註視圖
- (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]; if (!annatationView) { annatationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifer]; //annatationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier: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); //能夠設置爲UIImage,可是沒有點擊事件 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]; } return annatationView; }
- (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"); }
Demo下載地址: