【iOS開發(fā)筆記】系統(tǒng)權(quán)限的獲取和請求

前言

iOS開發(fā)避免不開系統(tǒng)權(quán)限的問題思恐,如何在APP中以更加友好的方式向用戶展示系統(tǒng)權(quán)限沾谜,似乎也是開發(fā)過程中指的深思的一件事。

那如何提高用戶獲取權(quán)限的通過率呢胀莹?以下幾種方式或許是不錯的嘗試:

1.在用戶打開app時就向用戶請求權(quán)限基跑。

  1. 告知用戶授權(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)限的獲取暑诸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚌讼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子个榕,更是在濱河造成了極大的恐慌篡石,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件西采,死亡現(xiàn)場離奇詭異凰萨,居然都是意外死亡,警方通過查閱死者的電腦和手機械馆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門胖眷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人霹崎,你說我怎么就攤上這事珊搀。” “怎么了尾菇?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵境析,是天一觀的道長。 經(jīng)常有香客問我派诬,道長劳淆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任默赂,我火速辦了婚禮沛鸵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缆八。我一直安慰自己曲掰,他們只是感情好,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布耀里。 她就那樣靜靜地躺著蜈缤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冯挎。 梳的紋絲不亂的頭發(fā)上底哥,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天咙鞍,我揣著相機與錄音,去河邊找鬼趾徽。 笑死续滋,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的孵奶。 我是一名探鬼主播疲酌,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼了袁!你這毒婦竟也來了朗恳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤载绿,失蹤者是張志新(化名)和其女友劉穎粥诫,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崭庸,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡怀浆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了怕享。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片执赡。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖函筋,靈堂內(nèi)的尸體忽然破棺而出沙合,到底是詐尸還是另有隱情,我是刑警寧澤驻呐,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布灌诅,位于F島的核電站,受9級特大地震影響含末,放射性物質(zhì)發(fā)生泄漏猜拾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一佣盒、第九天 我趴在偏房一處隱蔽的房頂上張望挎袜。 院中可真熱鬧,春花似錦肥惭、人聲如沸盯仪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽全景。三九已至,卻和暖如春牵囤,著一層夾襖步出監(jiān)牢的瞬間爸黄,已是汗流浹背滞伟。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留炕贵,地道東北人梆奈。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像称开,于是被迫代替她去往敵國和親亩钟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353