- iOS的定位服務用到的框架是#import <CoreLocation/CoreLocation.h>
- 定位中用到的類是CLLocationManager
一.iOS8.0之前的定位
- 向用戶描述授權的信息需要在info.plist中配以下key

- 后台情況下開啟定位服務需要進行如下圖配置

二.iOS8.0之后的定位(包含iOS8.0)
- iOS8.0之后前台定位授權和后台定位授權需要調用下面對應的方法
// 前台定位授權 官方文檔中說明info.plist中必須有NSLocationWhenInUseUsageDescription鍵 [_mgr requestWhenInUseAuthorization];
或者
// 前后台定位授權 官方文檔中說明info.plist中必須有NSLocationAlwaysUsageDescription鍵 [_mgr requestAlwaysAuthorization];
-
iOS9新特性-只開啟前台定位時, 臨時開啟后台定位功能
在之前的版本如果只開啟了用戶使用期間定位, 就無法后台定位. iOS9更加靈活的提供了屬性, 可以再需要的時候臨時開啟后台定位.
首先設置allowsBackgroundLocationUpdates屬性為YES
然后需要增加plist鍵值對: Required background modes : App registers for location updates

三.版本不同的適配問題(兩種方法)
- 方法一:
// 方法一:判斷iOS版本號 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { // 前台定位授權 官方文檔中說明info.plist中必須有NSLocationWhenInUseUsageDescription鍵 [_mgr requestWhenInUseAuthorization]; // 前后台定位授權 官方文檔中說明info.plist中必須有NSLocationAlwaysUsageDescription鍵 [_mgr requestAlwaysAuthorization]; }
- 方法二:高大上的方法
// 方法二:判斷位置管理者能否響應iOS8之后的授權方法 if ([_mgr respondsToSelector:@selector(requestAlwaysAuthorization)]) { // // 前台定位授權 官方文檔中說明info.plist中必須有NSLocationWhenInUseUsageDescription鍵 // [_mgr requestWhenInUseAuthorization]; // 前后台定位授權 官方文檔中說明info.plist中必須有NSLocationAlwaysUsageDescription鍵 [_mgr requestAlwaysAuthorization]; }
三.其余細節問題
- 位置管理者的精確度
/** kCLLocationAccuracyBestForNavigation; --> 最適合導航 kCLLocationAccuracyBest; --> 最好的 kCLLocationAccuracyNearestTenMeters; --> 附近10米 kCLLocationAccuracyHundredMeters; --> 100米 kCLLocationAccuracyKilometer; --> 1000米 kCLLocationAccuracyThreeKilometers; --> 3000米 */ // 設置定位所需的精度 枚舉值 精確度越高越耗電 self.mgr.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
- 位置管理者的過濾器,沒移動制定的距離定位一次
// 每100米更新一次定位 self.mgr.distanceFilter = 100;
四.代理方法中獲取定位到的位置信息
- CLLocation類,這里通過練習來講解一下這個類,類中包含了獲取到的用戶位置的信息
- coordinate --> 坐標,經度和緯度
- altitude --> 海拔
- horizontalAccuracy --> 水平精度
- verticalAccuracy -->垂直精度
- course --> 航向
- speed --> 速度
- timestamp --> 時間戳
- distanceFromLocation: --> 計算兩個位置之間的距離
- 練習要求: 打印:北偏東 30度方向 走了100米 位置管理者的懶加載在下方
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations { CLLocation *location = [locations lastObject]; // 打印:北偏東 30度方向 走了100米 // 1.計算方向 NSArray *arr = @[@"北偏東",@"東偏南",@"南偏西",@"西偏北"]; int index = (int)(location.course / 90); // course航向 NSString *direction = arr[index]; // 2.計算度數 int degree = (int)location.course % 90; if (degree == 0) { direction = [@"正" stringByAppendingString:[direction substringToIndex:1]]; } // 3.計算路程 double distance = 0; if (self.preivousLoc) { distance = [location distanceFromLocation:self.preivousLoc]; // 計算兩點之間的距離 } self.preivousLoc = location; // 4.拼串 NSString *result; if (degree != 0) { result = [NSString stringWithFormat:@"%@ %zd度方向 走了%f米",direction,degree,distance]; } else { result = [NSString stringWithFormat:@"%@ 方向 走了%f米",direction,distance]; } NSLog(@"%@",result); }
五.代理方法中監聽授權狀態的改變
// 代理方法中監聽授權的改變,被拒絕有兩種情況,一是真正被拒絕,二是服務關閉了 - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { switch (status) { case kCLAuthorizationStatusNotDetermined: { NSLog(@"用戶未決定"); break; } // 系統預留字段,暫時還沒用到 case kCLAuthorizationStatusRestricted: { NSLog(@"受限制"); break; } case kCLAuthorizationStatusDenied: { // 被拒絕有兩種情況 1.設備不支持定位服務 2.定位服務被關閉 if ([CLLocationManager locationServicesEnabled]) { NSLog(@"真正被拒絕"); // 跳轉到設置界面 NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url]; } } else { NSLog(@"沒有開啟此功能"); } break; } case kCLAuthorizationStatusAuthorizedAlways: { NSLog(@"前后台定位授權"); break; } case kCLAuthorizationStatusAuthorizedWhenInUse: { NSLog(@"前台定位授權"); break; } default: break; } }
六.練習詳細代碼
#import "ViewController.h" #import <CoreLocation/CoreLocation.h> @interface ViewController ()<CLLocationManagerDelegate> /** 位置管理者 */ @property(nonatomic,strong) CLLocationManager *mgr; @end @implementation ViewController #pragma mark - 懶加載 - (CLLocationManager *)mgr { if (_mgr == nil) { // 實例化位置管理者 _mgr = [[CLLocationManager alloc] init]; // 指定代理,代理中獲取位置數據 _mgr.delegate = self; // 兼容iOS8之后的方法 // 方法一:判斷iOS版本號 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { // 前台定位授權 官方文檔中說明info.plist中必須有NSLocationWhenInUseUsageDescription鍵 [_mgr requestWhenInUseAuthorization]; // 前后台定位授權 官方文檔中說明info.plist中必須有NSLocationAlwaysUsageDescription鍵 [_mgr requestAlwaysAuthorization]; } // 方法二:判斷位置管理者能否響應iOS8之后的授權方法 if ([_mgr respondsToSelector:@selector(requestAlwaysAuthorization)]) { // // 前台定位授權 官方文檔中說明info.plist中必須有NSLocationWhenInUseUsageDescription鍵 // [_mgr requestWhenInUseAuthorization]; // 前后台定位授權 官方文檔中說明info.plist中必須有NSLocationAlwaysUsageDescription鍵 [_mgr requestAlwaysAuthorization]; } // 允許后台獲取用戶位置(iOS9.0) if([[UIDevice currentDevice].systemVersion floatValue] >= 9.0) { // 一定要勾選后台模式 location updates _lM.allowsBackgroundLocationUpdates = YES; } } return _mgr; } - (void)viewDidLoad { [super viewDidLoad]; // 開啟位置更新 [self.mgr startUpdatingLocation]; /** kCLLocationAccuracyBestForNavigation; --> 最適合導航 kCLLocationAccuracyBest; --> 最好的 kCLLocationAccuracyNearestTenMeters; --> 附近10米 kCLLocationAccuracyHundredMeters; --> 100米 kCLLocationAccuracyKilometer; --> 1000米 kCLLocationAccuracyThreeKilometers; --> 3000米 */ // 設置定位所需的精度 枚舉值 精確度越高越耗電 self.mgr.desiredAccuracy = kCLLocationAccuracyBestForNavigation; // 每100米更新一次定位 self.mgr.distanceFilter = 100; } #pragma mark - CLLocationManagerDelegate - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations { NSLog(@"已經定位"); } // 代理方法中監聽授權的改變,被拒絕有兩種情況,一是真正被拒絕,二是服務關閉了 - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { switch (status) { case kCLAuthorizationStatusNotDetermined: { NSLog(@"用戶未決定"); break; } // 系統預留字段,暫時還沒用到 case kCLAuthorizationStatusRestricted: { NSLog(@"受限制"); break; } case kCLAuthorizationStatusDenied: { // 被拒絕有兩種情況 1.設備不支持定位服務 2.定位服務被關閉 if ([CLLocationManager locationServicesEnabled]) { NSLog(@"真正被拒絕"); // 跳轉到設置界面 NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; if ([[UIApplication sharedApplication] canOpenURL:url]) { [[UIApplication sharedApplication] openURL:url]; } } else { NSLog(@"沒有開啟此功能"); } break; } case kCLAuthorizationStatusAuthorizedAlways: { NSLog(@"前后台定位授權"); break; } case kCLAuthorizationStatusAuthorizedWhenInUse: { NSLog(@"前台定位授權"); break; } default: break; } } @end
