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
原文地址:https://www.cnblogs.com/jiqiaochun/p/8548026.html