美文网首页
iOS开发-浅谈定位权限

iOS开发-浅谈定位权限

作者: Engandend | 来源:发表于2018-09-04 11:14 被阅读0次

    [TOC]

    在iOS8之后,关于权限信息有些更改
    对于定位权限而言,相对其他的权限稍微麻烦一些

    1、key的配置

    1、使用app的时候使用位置信息

    NSLocationWhenInUseUsageDescription
    

    2、允许app一直使用位置信息

    NSLocationAlwaysUsageDescription
    

    3、允许2中选择同时存在 11.4之后有用

    NSLocationAlwaysAndWhenInUseUsageDescription
    

    2、api的调用

    有2个api:

    requestWhenInUseAuthorization    //when-in-use
    
    requestAlwaysAuthorization        //Always
    

    这2个api从表面来看,意思是请求when-in-useAlways
    但是实测发现when-in-use完全可以覆盖Always,也就是说Always完全可以不用,让when-in-use 根据plist中的key配置自动去完成所需要的权限弹框。

    具体测试如下:
    1)、11.4系统以下(上面说到 alwayandwhen 对11.4以下无用,这里不测试)

    配置信息 requestWhenInUseAuthorization requestAlwaysAuthorization
    1 请求1 无效
    2 请求2 请求2
    1 2 请求2 请求2

    2)、11.4系统以后

    配置信息 requestWhenInUseAuthorization requestAlwaysAuthorization
    1 请求1 无效
    2 无效 无效
    3 无效 无效
    1 2 请求1 无效
    1 3 请求1、2 请求1、2
    1 2 3 请求1、2 请求1、2

    基于以上测试结果, 我们可以发现:
    11.4之前的系统:
    12可以单独存在。
    11.4之后的系统:
    所有的权限必须基于1而存在。

    在app开发中,现在一般最低适配的系统是8或者9,所以在plist中配置key的时候,1是必须的,如果需要用到一直使用位置权限,那么1 2 3 3个key都需要配置

    3、权限请求

    对于app中权限的请求,相册、相机等都有系统提供的api直接去请求权限,但是位置信息比较麻烦,在这里做了一个封装:
    具体代码如下:
    JEAuthorityTool.h文件
    引入系统库 #import <CoreLocation/CoreLocation.h>

    
    /**
     请求定位权限
    
     @param block 结果
     */
    +(void)je_authorityLocationRequest:(void(^)(BOOL granted,
                                                CLAuthorizationStatus status))block;
    
    /**
     *  获取定位使用权限
     *
     *  @param location BOOL 表示系统所有app有没有打开定位  status app的定位权限状态
    */
    +(void)je_authorityLocation:(void(^)(BOOL canLocation ,
                                         CLAuthorizationStatus status))location;
    

    JEAuthorityTool.m文件

    #import "JEAuthorityTool.h"
    
    typedef void(^je_authorityLocationBLock)(BOOL granted,CLAuthorizationStatus state);
    
    @interface JEAuthorityTool ()<CLLocationManagerDelegate>
    
    @property (strong,  nonatomic)  CLLocationManager   *locationManager;
    @property (copy,    nonatomic)  je_authorityLocationBLock   locationBlock;
    
    @end
    
    
    static  dispatch_once_t onceToken;
    + (JEAuthorityTool *)sharedLocationManage
    {
        static  JEAuthorityTool *__singletion;
        dispatch_once(&onceToken, ^{
            __singletion=[[self alloc] init];
        });
        return __singletion;
    }
    -(instancetype)init
    {
        if (self = [super init])
        {
            self.locationManager = [CLLocationManager new];
        }
        return self;
    }
    
    +(void)je_authorityLocationRequest:(void(^)(BOOL granted,
                                                CLAuthorizationStatus status))block
    {
        [self sharedLocationManage].locationBlock = block;
        
        BOOL canUser;
        CLAuthorizationStatus status;
        [self je_authorityLocation:&canUser status:&status];
        
        if (status == kCLAuthorizationStatusNotDetermined)
        {
            CLLocationManager *manager = [self sharedLocationManage].locationManager;
            manager.delegate = [self sharedLocationManage];
            [manager requestWhenInUseAuthorization];
            
            NSDictionary *dic = [NSBundle mainBundle].infoDictionary;
            BOOL boolWhen = locationContentWithStr(@"NSLocationWhenInUseUsageDescription",dic);
            BOOL boolAlway = locationContentWithStr(@"NSLocationAlwaysUsageDescription",dic);
            
            BOOL show = NO;
            if (@available(iOS 11.4, *))
                show = boolWhen;
            else
                show = (boolAlway || boolWhen);
            
            if (!show) {
                NSLog(@"---------------------\n\
                      ⚠️如果第一次没有弹出权限请求\n\
                      请在plist中配置位置权限信息\n\
                      按照实际需求,需要配置以下key\n\
                      NSLocationWhenInUseUsageDescription   和\n\
                      NSLocationAlwaysUsageDescription      和\n\
                      NSLocationAlwaysAndWhenInUseUsageDescription\n\
                      ---------------------");
            }
        }
        else{
            if ([self sharedLocationManage].locationBlock)
            {
                [self sharedLocationManage].locationBlock(canUser, status);
                [self sharedLocationManage].locationBlock = nil;
            }
            [self sharedLocationManage].locationManager = nil;
            onceToken = 0;
        }
    }
    
    BOOL locationContentWithStr(NSString *str, NSDictionary *dic)
    {
        if ([[dic allKeys] containsObject:str])
        {
            id value =  dic[str];
            if ([value isKindOfClass:[NSString class]])
            {
                return YES;
            }
        }
        return NO;
    }
    
    
    -(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
    {
        if (status != kCLAuthorizationStatusNotDetermined)
        {
            if (self.locationBlock) {
                self.locationBlock([[self class] je_authorityBoolLocation ], status);
                self.locationBlock = nil;
            }
            self.locationManager = nil;
            onceToken = 0;
        }
    }
    
    +(void)je_authorityLocation:(void (^)(BOOL, CLAuthorizationStatus))location
    {
        if (location) {
            if (![CLLocationManager locationServicesEnabled]) {
                NSLog(@"系统所有app都没有打开定位功能");
                location(NO,kCLAuthorizationStatusDenied);
                return;
            }
            
            CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
            location(YES,status);
        }
    }
    
    +(void)je_authorityLocation:(BOOL *)systemOpen status:(CLAuthorizationStatus *)status
    {
        if (![CLLocationManager locationServicesEnabled]) {
            NSLog(@"系统所有app都没有打开定位功能");
            
            *systemOpen = NO;
            *status = kCLAuthorizationStatusDenied;
        }
        else
        {
            *systemOpen = YES;
            *status = [CLLocationManager authorizationStatus];
        }
    }
    
    +(BOOL)je_authorityBoolLocation
    {
        BOOL systemOpen;
        CLAuthorizationStatus status;
        [self je_authorityLocation:&systemOpen status:&status];
        if (systemOpen == NO) {
            return NO;
        }
        else
        {
            if (status == kCLAuthorizationStatusNotDetermined ||
                status == kCLAuthorizationStatusAuthorizedAlways ||
                status == kCLAuthorizationStatusAuthorizedWhenInUse)
            {
                return YES;
            }
            else{
                return NO;
            }
        }
    }
    
    

    修改补充:

    (2018-10-30)

    1、2楼的兄弟提到Privacy - Location Usage Description(NSLocationUsageDescription),这个是iOS6-8的时候才使用的一个位置权限配置key,iOS8以后就舍弃了这个,因为在8之前,没有“使用时定位”和“一直定位”的区分。
    如果要适配8之前的系统,如果能加的话还是要加上(我目前的项目都是最低适配8,而且模拟器最低也只能下到8.1的版本,所以无法测试)。参考链接(在页面内搜索NSLocationUsageDescription)

    相关文章

      网友评论

          本文标题:iOS开发-浅谈定位权限

          本文链接:https://www.haomeiwen.com/subject/viyiwftx.html