iOS开发

地图之CLLocationManager的使用

2020-08-05  本文已影响0人  枫叶1234

授权状态

.Restricted 表示GPS功能受限于某些限制,无法使用定位服务,例如parental controls

kCLAuthorizationStatusNotDetermined //用户没有选择是否要使用定位服务(弹框没选择,或者根本没有弹框

kCLAuthorizationStatusRestricted //定位服务授权状态受限制,可能由于活动限制了定位服务,并且用户不能改变当前的权限,这个状态有可能不是用户拒绝的,但是也有可能是用户拒绝的。官网说的,具体没遇到过(遇到过的童鞋请告知谢谢)

kCLAuthorizationStatusDenied //用户在设置中关闭定位功能,或者用户明确的在弹框之后选择禁止定位

kCLAuthorizationStatusAuthorized //用户已经明确使用定位功能

kCLAuthorizationStatusAuthorizedWhenInUse //用户在使用期间允许使用定位功能

kCLAuthorizationStatusAuthorizedAlways //App始终允许使用定位功能

1.iOS8以前使用CLLocationManager

// 1.设置位置管理者属性
@property (nonatomic, strong) CLLocationManager *lcManager;
// 2.判断是否打开了位置服务
if ([CLLocationManager locationServicesEnabled]) {
    // 创建位置管理者对象
    self.lcManager = [[CLLocationManager alloc] init];
    self.lcManager.delegate = self; // 设置代理
    // 设置定位距离过滤参数 (当本次定位和上次定位之间的距离大于或等于这个值时,调用代理方法)
    self.lcManager.distanceFilter = 100;
    self.lcManager.desiredAccuracy = kCLLocationAccuracyBest; // 设置定位精度(精度越高越耗电)
    [self.lcManager startUpdatingLocation]; // 开始更新位置
}
/** 获取到新的位置信息时调用*/
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    NSLog(@"定位到了");
}
/** 不能获取位置信息时调用*/
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
    NSLog(@"获取定位失败");
}
Snip20200731_2.png Snip20200731_3.png

2.iOS8.0之后使用CLLocationManager

1.requestWhenInUseAuthorization

image.png
[_lcManager requestWhenInUseAuthorization];
Snip20200731_4.png

iOS 后台定位 蓝条问题

image.png
蓝条问题的产生机理和处理办法:

CLLocationManager管理类的配置

_locationManager = [[CLLocationManager alloc] init];
    _locationManager.delegate = self;
    _locationManager.distanceFilter = 100;
    _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
 
    if ([[UIDevice currentDevice] systemVersion].floatValue >= 8) {
        /*
         有这么一种说法
         如果两个请求授权的方法都执行了,会出现以下情况
         1.requestWhenInUseAuthorization写在前面,第一次打开程序时请求授权,如果勾选了后台模式,进入后台会出现蓝条提示正在定位。当程序退出,第二次打开程序时requestAlwaysAuthorization 会再次请求授权。之后进入后台就不会出现蓝色状态栏。
         2.requestAlwaysAuthorization写在前面, requestWhenInUseAuthorization写在后面,只会在第一次打开程序时请求授权,因为requestAlwaysAuthorization得到的授权大于requestWhenInUseAuthorization得到的授权
         */
        [_locationManager requestAlwaysAuthorization];
        [_locationManager requestWhenInUseAuthorization];
    }
    if ([[UIDevice currentDevice] systemVersion].floatValue >= 9) {
        /*
         allowsBackgroundLocationUpdates:是否允许后台定位,默认为NO,只在iOS9.0之后起作用。
         设为YES时,必须保证Background Modes 中的Location updates处于选中状态,否则会抛出异常。
         在用户选择仅在使用应用期间获取位置权限的情况下,当应用进入后台,手机桌面顶部是否出现蓝条,这句代码起着关键性作用。
         首先,这句代码仅在requestWhenInUseAuthorization状态下才起作用,否则不起作用。当设为YES,就是允许在requestWhenInUseAuthorization此状态下,即使App进入后台,但是没杀死,那么就依然可以后台定位。并且顶部给个蓝条闪烁,目的是在于实时提醒用户:你这个App一直在获取你的位置信息哟,如果你感到不需要继续获取了,就杀死该App吧!所以一直蓝条闪烁。
         当设置为NO,就是在requestWhenInUseAuthorization状态下,App进入后台,立即停止后台定位。
         */
        _locationManager.allowsBackgroundLocationUpdates = YES;
        /*
         requestLocation和startUpdatingLocation这两个方法非常类似,都会立即返回结果,将获取的定位信息传递给委托对象的locationManager:didUpdateLocations:消息。
         不同点:
         startUpdatingLocation:可以持续获取定位。当设备移动的距离超过设定的distanceFilter属性值时,接收器会再次生成一条更新消息。
         requestLocation:只产生一次定位信息,在此之后定位服务就停止了。并且:当使用这个方法时,委托对象必须要实现locationManager:didUpdateLocations:和locationManager:didFailWithError:方法。
         */
        [_locationManager requestLocation];
    } else {
        [_locationManager startUpdatingLocation];
        
    }

其实在上段代码注释中已经写得较清楚了。

蓝条问题的产生前提:只在requestWhenInUseAuthorization这个状态下才会出现。

蓝条出现的目的:因为用户选择的是仅在应用使用期间获取位置,所以当app进入后台后,系统将以蓝条闪烁的形式不断提醒用户:主人,某某App一直在后台获取你的位置权限哟,如果你不需要用到了,你就直接将该App杀死吧,不然挺耗电的,如果有需要就当我没说哈。

蓝条出现与否的背后代码操控者:_locationManager.allowsBackgroundLocationUpdates = YES;如果不想出现蓝条,直接设置为NO,或者注释,因为默认为NO。

另外,蓝条出现与否的另一种说法:跟下面两句代码的执行顺序有关

        [_locationManager requestAlwaysAuthorization];
        [_locationManager requestWhenInUseAuthorization];

2.requestAlwaysAuthorization

image.png Snip20200731_5.png

这边为什么还是显示的User的文档呢?

因为:在ios11中,NSLocationAlwaysUsageDeion 被当做NSLocationWhenInUseUsageDeion 来处理了

在IOS11,原有的NSLocationAlwaysUsageDeion被降级为NSLocationWhenInUseUsageDeion。因此,在原来项目中使用requestAlwaysAuthorization获取定位权限,而未在plist文件中配置NSLocationAlwaysAndWhenInUseUsageDeion,系统框不会弹出。建议新旧key值都在plist里配置,反正我试下来是没有问题,唯一的区别是使用requestAlwaysAuthorization获取权限 IOS11系统弹框会把几种权限级别全部列出,供用户选择,显然更人性化了哈~~

在plist文件中如果不包含“ NSLocationAlwaysAndWhenInUseUsageDeion”

会报:The app's Info.plist must contain both “NSLocationAlwaysAndWhenInUseUsageDescription” and “NSLocationWhenInUseUsageDescription” keys with string values explaining to the user how the app uses this data 这个错误

还有一种情况:

截屏2020-07-31 下午5.28.59.png

当你第一次用requestWhenInUseAuthorization请求了
会弹出

Snip20200731_4.png

如果第二次用“requestAlwaysAuthorization”请求,就会弹出


image.png

这边的文案显示的plist中配置的 NSLocationAlwaysAndWhenInUseUsageDeion的文案
说明弹出这个,必须在plist中配置NSLocationAlwaysAndWhenInUseUsageDeion

3.注意

4.判断是否开启了定位服务

if ([CLLocationManager locationServicesEnabled]) { // 判断是否打开了位置服务
        [self.lcManager startUpdatingLocation]; // 开始更新位置
    }

5.适配版本号的方法

if ([[UIDevice currentDevice].systemVersion floatValue] >=8.0 ) {
[_lcManager requestAlwaysAuthorization];
}
if ([_lcManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
            [_lcManager requestWhenInUseAuthorization];
        }

6.监听定位服务状态的改变

/** 定位服务状态改变时调用*/
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
    switch (status) {
        case kCLAuthorizationStatusNotDetermined:
        {
            NSLog(@"用户还未决定授权");
            break;
        }
        case kCLAuthorizationStatusRestricted:
        {
            NSLog(@"访问受限");
            break;
        }
        case kCLAuthorizationStatusDenied:
        {
            // 类方法,判断是否开启定位服务
            if ([CLLocationManager locationServicesEnabled]) {
                NSLog(@"定位服务开启,被拒绝");
            } else {
                NSLog(@"定位服务关闭,不可用");
            }
            break;
        }
        case kCLAuthorizationStatusAuthorizedAlways:
        {
            NSLog(@"获得前后台授权");
            break;
        }
        case kCLAuthorizationStatusAuthorizedWhenInUse:
        {
            NSLog(@"获得前台授权");
            break;
        }
        default:
            break;
    }
}

7.代理方法返回的 locations 信息

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
    CLLocation *location = [locations firstObject];
    NSLog(@"%@", location);
}

3.iOS9.0之后使用CLLocationManager

    if ([CLLocationManager locationServicesEnabled]) { // 判断是否打开了位置服务
        [self.lcManager requestLocation];
    }
if ([[UIDevice currentDevice].systemVersion floatValue] >=8.0 ) {
     // iOS0.0:如果当前的授权状态是使用是授权,那么App退到后台后,将不能获取用户位置,即使勾选后台模式:location
    [_lcManager requestWhenInUseAuthorization];
    }
// iOS9.0+ 要想继续获取位置,需要使用以下属性进行设置(注意勾选后台模式:location)但会出现蓝条
if ([_lcManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
    _lcManager.allowsBackgroundLocationUpdates = YES;
}
上一篇下一篇

猜你喜欢

热点阅读