iOS 系统权限检测功能

自从iOS8增加了权限需要征得用户同意后,后续iOS对权限的要求越来严格,记录一下各种权限的获取方法

1、定位权限(info.plist需要添加LocationWhenInUseUsageDescription + LocationAlwaysUsageDescription)

需要获取用户此时此刻的位置信息的时候需要使用到定位权限。
使用到了#import // 定位框架
权限状态获取方法是:

CLAuthorizationStatus locationstats = [CLLocationManager authorizationStatus];

获取到的状态有:

typedef NS_ENUM(int, CLAuthorizationStatus) {
    kCLAuthorizationStatusNotDetermined = 0, // 还未请求过权限,一般是APP首次安装,然后第一次请求权限的时候才会出现这个状态,然后需要主动触发权限请求
    kCLAuthorizationStatusRestricted, // 拒绝状态
    kCLAuthorizationStatusDenied,//  用户已允许状态
    kCLAuthorizationStatusAuthorizedAlways NS_ENUM_AVAILABLE(10_12, 8_0),// “始终”定位
    kCLAuthorizationStatusAuthorizedWhenInUse NS_ENUM_AVAILABLE(NA, 8_0),// “使用应用期间”定位
    kCLAuthorizationStatusAuthorized NS_ENUM_DEPRECATED(10_6, NA, 2_0, 8_0, "Use kCLAuthorizationStatusAuthorizedAlways") // 此枚举已经废弃,使用kCLAuthorizationStatusAuthorizedAlways替代
};

当系统API返回的状态是kCLAuthorizationStatusNotDetermined还未授权过的状态的时候,我们需要主动发起授权请求,如果定位仅仅是“在APP使用期间”才涉及到定位需求的话,那么使用requestWhenInUseAuthorization方法请求权限,如果是无论什么时候都需要定位权限的话,那么使用requestAlwaysAuthorization方法请求权限,请求方法如下:

    CLLocationManager * locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    // 在app打开期间使用定位权限
    [locationManager requestWhenInUseAuthorization];
    // app在后台也可以持续定位
    [locationManager requestAlwaysAuthorization];

请求方法二选一。接着在CLLocationManagerDelegate代理里面实现

// 当此应用程序的授权状态更改时调用
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
}

方法,返回的status就是当前用的选择的状态了。需要注意的是,如果CLLocationManager对象被释放了,那么弹窗也会消失,所以可以把CLLocationManager对象变成属性或者成员变量。

2、消息通知

推送通知需要使用的框架是#import // 通知框架
权限状态获取方法是:
此时要区分系统版本获取,在iOS10之后使用:

[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
    // 获取状态
    UNAuthorizationStatus authorizationStatus = settings.authorizationStatus;
}];

获取到的状态有:

// 该枚举在iOS 10 之后才能使用
typedef NS_ENUM(NSInteger, UNAuthorizationStatus) {
    UNAuthorizationStatusNotDetermined = 0, // 还未授权
    UNAuthorizationStatusDenied, // 被拒绝
    UNAuthorizationStatusAuthorized // 用户允许
} __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);

请求权限通知的API方法:

// User authorization is required for applications to notify the user using UNUserNotificationCenter via both local and remote notifications.
- (void)requestAuthorizationWithOptions:(UNAuthorizationOptions)options completionHandler:(void (^)(BOOL granted, NSError *__nullable error))completionHandler;

// 使用方法
UNUserNotificationCenter * center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
    //  granted 代表允许与否    
    dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程
    });                       
}];

值得注意的是,此时block回调是在任意线程中的,所以需要回到主线程内处理其他代码
UNAuthorizationOptions枚举是:

typedef NS_OPTIONS(NSUInteger, UNAuthorizationOptions) {
    UNAuthorizationOptionBadge   = (1 << 0),  // 角标
    UNAuthorizationOptionSound   = (1 << 1), // 声音
    UNAuthorizationOptionAlert   = (1 << 2), // 弹窗
    UNAuthorizationOptionCarPlay = (1 << 3),  // 车载
} __IOS_AVAILABLE(10.0) __TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0);

在iOS10之前使用

BOOL result = [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
// result 就是授权状态 ...

3、录音权限(info.plist需要添加MicrophoneUsageDescription)

录音权限就要使用#import // 音视频框架
请求录音权限通知的API方法:

    AVAudioSession * audioSession = [AVAudioSession sharedInstance];
    [audioSession requestRecordPermission:^(BOOL granted) {
        //  granted 代表允许与否  
        dispatch_async(dispatch_get_main_queue(), ^{
            //  回到主线程
        });
    }];

值得注意的是,此时block回调是在任意线程中的,所以需要回到主线程内处理其他代码

4、相机权限(info.plist需要添加CameraUsageDescription)

相机权限就要使用#import // 音视频框架
获取当前权限状态API:

AVAuthorizationStatus cameraAuthorizationStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

获取到的状态有:

typedef NS_ENUM(NSInteger, AVAuthorizationStatus) {
    AVAuthorizationStatusNotDetermined = 0, // 未授权,需要调用方法触发授权
    AVAuthorizationStatusRestricted    = 1, // 已被限制,例如家长控制等等
    AVAuthorizationStatusDenied        = 2, //  已被拒绝
    AVAuthorizationStatusAuthorized    = 3, // 已允许
} NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;

请求相机权限通知的API方法:

[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
    // granted 代表允许与否  
    dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程
    });
 }];

值得注意的是,此时block回调是在任意线程中的,所以需要回到主线程内处理其他代码

5、相册权限(info.plist需要添加NSPhotoLibraryUsageDescription)

需要查看手机相册需要使用 iOS8.0之前使用#import 和 iOS8.0之后使用 #import
获取当前相册权限状态API,在iOS8.0之后使用:

PHAuthorizationStatus PHAssetsAuthorizationStatus = [PHPhotoLibrary authorizationStatus];

获取到的状态有:

typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
    PHAuthorizationStatusNotDetermined = 0,  // 还未授权,需要触发授权方法
    PHAuthorizationStatusRestricted,  // 已被限制,例如家长控制等等
    PHAuthorizationStatusDenied,   // 已被拒绝
    PHAuthorizationStatusAuthorized  // 已允许
} PHOTOS_AVAILABLE_IOS_TVOS(8_0, 10_0);

请求相册权限通知的API方法:

[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程操作
    });
}];

值得注意的是,此时block回调是在任意线程中的,所以需要回到主线程内处理其他代码

iOS 8.0之前使用API:

ALAuthorizationStatus ALAssetsAuthorizationStatus = [ALAssetsLibrary authorizationStatus];

获取到的状态有:

typedef NS_ENUM(NSInteger, ALAuthorizationStatus) {
    ALAuthorizationStatusNotDetermined ,  // 还未授权,需要触发授权方法
    ALAuthorizationStatusRestricted ,  // 已被限制,例如家长控制等等
    ALAuthorizationStatusDenied ,  // 已被拒绝
    ALAuthorizationStatusAuthorized // 已允许 
} NS_DEPRECATED_IOS(6_0, 9_0, "Use PHAuthorizationStatus in the Photos framework instead");

当获取到的状态是ALAuthorizationStatusNotDetermined需要触发授权方法,授权API是:

[ALAssetsLibrary alloc] init] enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程
    });
} failureBlock:^(NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程
    });
}];

值得注意的是,此时block回调是在任意线程中的,所以需要回到主线程内处理其他代码

6、通讯录权限(info.plist需要添加ContactsUsageDescription)

需要查看通讯录权限需要使用 iOS9.0之前使用#import 和 iOS9.0之后使用 #import
获取通讯录权限状态API,在iOS9.0之后使用:

CNAuthorizationStatus authorizationStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];

获取到的状态有:

typedef NS_ENUM(NSInteger, CNAuthorizationStatus) {
    CNAuthorizationStatusNotDetermined = 0,  // 还未授权,需要触发授权方法
    CNAuthorizationStatusRestricted, // 已被限制,例如家长控制等等
    CNAuthorizationStatusDenied, // 已被拒绝
    CNAuthorizationStatusAuthorized // 已允许 
} NS_ENUM_AVAILABLE(10_11, 9_0);

当获取到的状态是CNAuthorizationStatusNotDetermined需要触发授权方法,授权API是:

[[[CNContactStore alloc] init] requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程操作
    });
 }];

值得注意的是,此时block回调是在任意线程中的,所以需要回到主线程内处理其他代码

iOS 9.0之前使用API:

ABAuthorizationStatus authorizationStatus = ABAddressBookGetAuthorizationStatus();

获取到的状态有:

typedef CF_ENUM(CFIndex, ABAuthorizationStatus) {
    kABAuthorizationStatusNotDetermined = 0,  // 还未授权,需要触发授权方法
    kABAuthorizationStatusRestricted, // 已被限制,例如家长控制等等 
    kABAuthorizationStatusDenied, // 已被拒绝            
    kABAuthorizationStatusAuthorized // 已允许            
} AB_DEPRECATED("use CNAuthorizationStatus");

当获取到的状态是kABAuthorizationStatusNotDetermined时,需要触发授权方法,授权API是:

ABAddressBookRef bookref = ABAddressBookCreateWithOptions(NULL, NULL);
ABAddressBookRequestAccessWithCompletion(bookref, ^(bool granted, CFErrorRef error) {
    //  这里granted是用户点击后的状态
});

7、日历权限 + 日历提醒事件权限 (info.plist需要添加CalendarsUsageDescription + RemindersUsageDescription)

需要查看日历权限需要使用 #import
获取当前权限状态API是:

// 获取日历权限
EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
// 获取提醒事件权限
EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeReminder];

获取到的状态有:

typedef NS_ENUM(NSInteger, EKAuthorizationStatus) {
    EKAuthorizationStatusNotDetermined = 0,  // 还未授权,需要触发授权方法
    EKAuthorizationStatusRestricted, // 已被限制,例如家长控制等等 
    EKAuthorizationStatusDenied, // 已被拒绝    
    EKAuthorizationStatusAuthorized, // 已允许      
} NS_AVAILABLE(10_9, 6_0);

当获取到的状态是EKAuthorizationStatusNotDetermined时,需要触发授权方法,授权API是:

// 触发日历权限API
[[[EKEventStore alloc] init] requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 需要回到主线程操作
    });
}];
// 触发提醒事件权限API
[[[EKEventStore alloc] init] requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError * _Nullable error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 需要回到主线程操作
    });
}];

值得注意的是,此时block回调是在任意线程中的,所以需要回到主线程内处理其他代码

8、语音识别功能权限 (info.plist需要添加SpeechRecognitionUsageDescription)

语音识别功能api接口只有在iOS10之后才有,所以最低都要从iOS10开始使用
需要使用语音识别功能需要使用 #import
获取当前权限状态API是:

SFSpeechRecognizerAuthorizationStatus status = [SFSpeechRecognizer authorizationStatus];

获取到的状态有:

typedef NS_ENUM(NSInteger, SFSpeechRecognizerAuthorizationStatus) {
    SFSpeechRecognizerAuthorizationStatusNotDetermined, // 还未授权,需要触发授权方法
    SFSpeechRecognizerAuthorizationStatusDenied, // 已被拒绝    
    SFSpeechRecognizerAuthorizationStatusRestricted, // 已被限制,例如家长控制等等 
    SFSpeechRecognizerAuthorizationStatusAuthorized, // 已允许    
} API_AVAILABLE(ios(10.0));

当获取到的状态是SFSpeechRecognizerAuthorizationStatusNotDetermined时,需要触发授权方法,授权API是:

[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 回到主线程操作
    });
}];

值得注意的是,此时block回调是在任意线程中的,所以需要回到主线程内处理其他代码

最后添加上所有权限key的代码

NSCalendarsUsageDescription
日历
NSCameraUsageDescription
需要获取您的摄像头信息
NSContactsUsageDescription
需要获取您的通讯录权限
NSLocationAlwaysUsageDescription
“始终”定位权限
NSLocationWhenInUseUsageDescription
“使用应用期间”定位权限
NSMicrophoneUsageDescription
需要获取您的麦克风权限
NSPhotoLibraryUsageDescription
需要获取您的相册信息
NSRemindersUsageDescription
提醒事项
NSSpeechRecognitionUsageDescription
语音识别权限

描述文字一定要说清楚作用,不然会被拒绝,拒绝,拒绝,当然这还要看审核人员的心情了。当事人已经被拒绝过了

你可能感兴趣的:(iOS 系统权限检测功能)