前言
iOS開發(fā)避免不開系統(tǒng)權(quán)限的問題思恐,如何在APP中以更加友好的方式向用戶展示系統(tǒng)權(quán)限沾谜,似乎也是開發(fā)過程中指的深思的一件事。
那如何提高用戶獲取權(quán)限的通過率呢胀莹?以下幾種方式或許是不錯的嘗試:
1.在用戶打開app時就向用戶請求權(quán)限基跑。
- 告知用戶授權(quán)權(quán)限后能夠獲得的好處后再向用戶請求權(quán)限。
3.在絕對必要的情況下才向用戶請求權(quán)限描焰。
4.在展示系統(tǒng)權(quán)限的提示框前媳否,現(xiàn)象用戶顯示自定義的提示框,如果用戶不允許栈顷,默認無操作逆日,如果用戶允許,再展示系統(tǒng)提示框萄凤。
上面的只是一些嘗試室抽,與本文的主要講述內(nèi)容關(guān)系不大,接下來我們主要來看一下常用的一些系統(tǒng)權(quán)限的狀態(tài)獲取以及主動喚起權(quán)限請求的方法靡努。
一坪圾、常用的權(quán)限及轉(zhuǎn)換枚舉
1 常用的權(quán)限
iOS系統(tǒng)的權(quán)限包括很多,本文主要整理了筆者常用的一些權(quán)限惑朦,后面隨著使用可能會繼續(xù)補充兽泄,目前本文中主要包含的權(quán)限如下:
相機權(quán)限
相冊權(quán)限
日歷權(quán)限
麥克風權(quán)限
推送權(quán)限
定位權(quán)限
提醒事項權(quán)限
通訊錄權(quán)限
互聯(lián)網(wǎng)權(quán)限
藍牙權(quán)限
2 自定義權(quán)限狀態(tài)枚舉
typedef NS_ENUM(NSInteger, TenAuthorizationStatus) {
/**未確定*/
TenAuthorizationStatusNotDetermined = 0,
/**限制*/
TenAuthorizationStatusRestricted,
/**拒絕*/
TenAuthorizationStatusDenied,
/**同意授權(quán)*/
TenAuthorizationStatusAuthorized,
};
二、權(quán)限的獲取及請求
1 相機權(quán)限
引入頭文件#import <AVFoundation/AVFoundation.h>
1.1 權(quán)限獲取
+(TenAuthorizationStatus)cameraStatue {
TenAuthorizationStatus status;
switch ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) {
case AVAuthorizationStatusAuthorized:
status = TenAuthorizationStatusAuthorized;
break;
case AVAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
case AVAuthorizationStatusRestricted:
status = TenAuthorizationStatusRestricted;
break;
default:
status = TenAuthorizationStatusDenied;
break;
}
return status;
}
1.2 權(quán)限請求
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
}];
1.3 info.plist設置
Privacy - Camera Usage Description
2 相冊權(quán)限
引入頭文件#import <Photos/Photos.h>
2.1 權(quán)限獲取
+(TenAuthorizationStatus)photoLibraryStatus {
TenAuthorizationStatus status;
EHIAuthorizationStatus status;
if (@available(iOS 14, *)) {
switch ([PHPhotoLibrary authorizationStatusForAccessLevel:PHAccessLevelReadWrite]) {
case PHAuthorizationStatusAuthorized:
//全部
status = TenAuthorizationStatusAuthorized;
break;
case PHAuthorizationStatusLimited:
//部分
status = TenAuthorizationStatusAuthorized;
break;
case PHAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
case PHAuthorizationStatusRestricted:
status = TenAuthorizationStatusRestricted;
break;
default:
status = TenAuthorizationStatusDenied;
break;
}
}else {
switch ([PHPhotoLibrary authorizationStatus]) {
case PHAuthorizationStatusAuthorized:
status = TenAuthorizationStatusAuthorized;
break;
case PHAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
case PHAuthorizationStatusRestricted:
status = TenAuthorizationStatusRestricted;
break;
default:
status = TenAuthorizationStatusDenied;
break;
}
}
return status;
}
2.2 權(quán)限請求
if (@available(iOS 14, *)) {
[PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelReadWrite handler:^(PHAuthorizationStatus status) {
}];
} else {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
}];
}
2.3 info.plist設置
存儲:
Privacy - Photo Library Additions Usage Description
查看:Privacy - Photo Library Usage Description
3 日歷權(quán)限
引入頭文件#import <EventKit/EventKit.h>
3.1 權(quán)限獲取
+(TenAuthorizationStatus)calendarStatus {
TenAuthorizationStatus status;
switch ([EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent]) {
case EKAuthorizationStatusAuthorized:
status = TenAuthorizationStatusAuthorized;
break;
case EKAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
case EKAuthorizationStatusRestricted:
status = TenAuthorizationStatusRestricted;
break;
default:
status = TenAuthorizationStatusDenied;
break;
}
return status;
}
3.2 權(quán)限請求
[[[EKEventStore alloc] init] requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
}];
3.3 info.plist設置
Privacy - Calendars Usage Description
4 麥克風權(quán)限
引入頭文件#import <AVFoundation/AVFoundation.h>
4.1 權(quán)限獲取
+(TenAuthorizationStatus)microphoneStatus {
TenAuthorizationStatus status;
switch ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]) {
case AVAuthorizationStatusAuthorized:
status = TenAuthorizationStatusAuthorized;
break;
case AVAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
case AVAuthorizationStatusRestricted:
status = TenAuthorizationStatusRestricted;
break;
default:
status = TenAuthorizationStatusDenied;
break;
}
return status;
}
4.2 權(quán)限請求
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
}];
4.3 info.plist設置
Privacy - Microphone Usage Description
5 推送權(quán)限
引入頭文件#import <UserNotifications/UserNotifications.h>
5.1 權(quán)限獲取
+(TenAuthorizationStatus)pushStatus {
if (@available(iOS 10.0, *)) {
dispatch_semaphore_t singal = dispatch_semaphore_create(0);//創(chuàng)建信號量
__block TenAuthorizationStatus status;
[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
switch (settings.authorizationStatus) {
case UNAuthorizationStatusDenied:
status = TenAuthorizationStatusDenied;
break;
case UNAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
default:
status = TenAuthorizationStatusAuthorized;
break;
}
dispatch_semaphore_signal(singal);//賦值完成發(fā)送信號
}];
dispatch_semaphore_wait(singal, DISPATCH_TIME_FOREVER);//等待信號
return status;
}
return ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone) ? TenAuthorizationStatusDenied : TenAuthorizationStatusAuthorized;
}
5.2 權(quán)限請求
if (@available(iOS 10.0, *)) {
[[UNUserNotificationCenter currentNotificationCenter]requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
}else {
//iOS10之前漾月,系統(tǒng)對于申請推送權(quán)限沒有具體的API病梢,只有設置NotificationSettings時,會自動請求權(quán)限
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:setting];
}
6 定位權(quán)限
引入頭文件#import <CoreLocation/CoreLocation.h>
6.1 權(quán)限獲取
+(TenAuthorizationStatus)locationStatus {
if (![CLLocationManager locationServicesEnabled]) {
//手機定位權(quán)限未開啟(針對全部應用)
return TenAuthorizationStatusRestricted;
}
TenAuthorizationStatus status;
switch ([EHILocationManager shareManager].authorizationStatus) {
case kCLAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
case kCLAuthorizationStatusDenied:
status = TenAuthorizationStatusDenied;
break;
case kCLAuthorizationStatusRestricted:
status = TenAuthorizationStatusRestricted;
break;
default:
status = TenAuthorizationStatusAuthorized;
break;
}
return status;
}
6.2 權(quán)限請求
定位權(quán)限請求與其他權(quán)限不動梁肿,請求的結(jié)果是在代理中返回的蜓陌,可以自己做一層封裝,與其他系統(tǒng)權(quán)限請求一樣用block的形式將結(jié)果返回吩蔑。
封裝方法調(diào)用
[[TenLocationManager shareManager] ten_requestLocationRequest:^(BOOL granted, CLAuthorizationStatus status) {
}];
TenLocationManager.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
@interface TenLocationManager : NSObject
/**系統(tǒng)定位權(quán)限*/
@property (nonatomic, readonly) CLAuthorizationStatus authorizationStatus;
/**單例方法*/
+(instancetype)shareManager;
/**
喚起請求定位權(quán)限
@param block 結(jié)果回調(diào)
*/
-(void)ten_requestLocationRequest:(void (^) (BOOL granted, CLAuthorizationStatus status))block;
@end
TenLocationManager.m
#import "TenLocationManager.h"
@interface TenLocationManager () <CLLocationManagerDelegate>
/**請求定位權(quán)限結(jié)果類*/
@property (nonatomic, copy) void (^locationAuthBlock) (BOOL granted, CLAuthorizationStatus state);
/**系統(tǒng)定位*/
@property (nonatomic, strong) CLLocationManager *sys_locationManager;
@end
static TenLocationManager *_locationManager;
@implementation TenLocationManager
/**構(gòu)造方法*/
+(instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (_locationManager == nil) {
_locationManager = [super allocWithZone:zone];
}
});
return _locationManager;
}
/**單例方法*/
+(instancetype)shareManager {
return [[self alloc] init];
}
/**喚起定位權(quán)限請求*/
-(void)ten_requestLocationRequest:(void (^)(BOOL, CLAuthorizationStatus))block {
self.locationAuthBlock = block;
[self.sys_locationManager requestWhenInUseAuthorization];
}
#pragma mark - CLLocationManagerDelegate
-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (self.locationAuthBlock) {
self.locationAuthBlock(status == kCLAuthorizationStatusAuthorizedWhenInUse, status);
}
}
#pragma mark - lazy getter
-(CLLocationManager *)sys_locationManager {
if (!_sys_locationManager) {
_sys_locationManager = [[CLLocationManager alloc]init];
_sys_locationManager.delegate = self;
}
return _sys_locationManager;
}
- (CLAuthorizationStatus)authorizationStatus {
if (@available(iOS 14, *)) {
return self.sys_locationManager.authorizationStatus;
}else {
return [CLLocationManager authorizationStatus];
}
}
6.3 info.plist設置
總是:
Privacy - Location Always Usage Description
使用中:Privacy - Location When In Use Usage Description
iOS14 之后钮热,增加精確定位功能,通過設置NSLocationDefaultAccuracyReduced為true來實現(xiàn)默認請求大概位置烛芬,否則是默認請求精確位置
如果是大概位置隧期,可單次請求精確位置飒责,配置NSLocationTemporaryUsageDescriptionDictionary字段設置請求原因,
喚起精確定位方法:[self.mgr requestTemporaryFullAccuracyAuthorizationWithPurposeKey:@"purposeKey"];
7 提醒事項權(quán)限
引入頭文件#import <EventKit/EventKit.h>
7.1 權(quán)限獲取
+(TenAuthorizationStatus)remindStatus {
TenAuthorizationStatus status;
switch ([EKEventStore authorizationStatusForEntityType:EKEntityTypeReminder]) {
case EKAuthorizationStatusAuthorized:
status = TenAuthorizationStatusAuthorized;
break;
case EKAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
case EKAuthorizationStatusRestricted:
status = TenAuthorizationStatusRestricted;
break;
default:
status = TenAuthorizationStatusDenied;
break;
}
return status;
}
7.2 權(quán)限請求
[[[EKEventStore alloc] init] requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
}];
7.3 info.plist設置
NSRemindersUsageDescription
8 通訊錄權(quán)限
引入頭文件
iOS 9.0前 #import <AddressBook/AddressBook.h>
iOS 9.0后 #import <Contacts/Contacts.h>
8.1 權(quán)限獲取
+(TenAuthorizationStatus)addressBookStatus {
TenAuthorizationStatus status;
if (@available(iOS 9.0, *)) {
switch ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]) {
case CNAuthorizationStatusAuthorized:
status = TenAuthorizationStatusAuthorized;
break;
case CNAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
case CNAuthorizationStatusRestricted:
status = TenAuthorizationStatusRestricted;
break;
default:
status = TenAuthorizationStatusDenied;
break;
}
} else {
switch (ABAddressBookGetAuthorizationStatus()) {
case kABAuthorizationStatusAuthorized:
status = TenAuthorizationStatusAuthorized;
break;
case kABAuthorizationStatusNotDetermined:
status = TenAuthorizationStatusNotDetermined;
break;
default:
status = TenAuthorizationStatusDenied;
break;
}
}
return status;
}
8.2 權(quán)限請求
if (@available(iOS 9.0, *)) {
[[[CNContactStore alloc] init] requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
}];
}else {
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
});
}
8.3 info.plist設置
Privacy - Contacts Usage Description
9 互聯(lián)網(wǎng)權(quán)限
引入頭文件#import <CoreTelephony/CTCellularData.h>
9.1 權(quán)限獲取
+(TenAuthorizationStatus)netStatus {
TenAuthorizationStatus status;
switch ([[CTCellularData alloc] init].restrictedState) {
case kCTCellularDataNotRestricted:
status = TenAuthorizationStatusAuthorized;
break;
case kCTCellularDataRestrictedStateUnknown:
status = TenAuthorizationStatusNotDetermined;
break;
default:
status = TenAuthorizationStatusDenied;
break;
}
return status;
}
9.2 權(quán)限請求
系統(tǒng)未提供接口供開發(fā)者手動請求網(wǎng)絡權(quán)限仆潮,iOS10以上系統(tǒng)宏蛉,應用首次請求網(wǎng)絡會自動彈出,一個應用只彈出一次鸵闪,卸載也不會重新彈出
10 藍牙權(quán)限
藍牙權(quán)限具體使用之前的表述有些問題檐晕,現(xiàn)在重新整理到了新的文章中:藍牙權(quán)限的獲取暑诸。