iOS地圖 -- 定位使用


  • 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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM