前言
開源庫JLAuthorizationManager :
Objective-C版本
Swift版本
上篇文章iOS開發(fā)中的這些權限,你搞懂了嗎呐赡?介紹了一些常用權限的獲取和請求方法链嘀,知道這些方法的使用基本上可以搞定大部分應用的權限訪問的需求。但是茫藏,這些方法并不全面霹琼,不能涵蓋住所有權限訪問的方法。
So售葡,筆者在介紹一下剩下的幾種權限的訪問方法和一些使用上的注意事項挟伙,希望能給大家的開發(fā)過程帶來一絲便利模孩。
最后烘豹,筆者將經常使用的權限請求方法封裝開源庫JLAuthorizationManager送給大家携悯,歡迎大家pull request 和 star~~
權限
- 語音識別筷笨;
- 媒體資料庫/Apple Music;
- Siri;
- 健康數(shù)據共享;
- 藍牙轴或;
- 住宅權限(HomeKit);
- 社交賬號體系權限仰禀;
- 活動與體能訓練記錄;
- 廣告標識答恶;
語音識別
- 引入頭文件: @import Speech;
- 首先判斷當前應用所處的權限狀態(tài),若當前狀態(tài)為NotDetermined(未確定)污呼,此時包竹,需要調用系統(tǒng)提供的請求權限方法周瞎,同時也是觸發(fā)系統(tǒng)彈窗的所在點;
- 該權限涉及到的類為** SFSpeechRecognizer**挤渐,具體代碼如下:
- (void)p_requestSpeechRecognizerAccessWithAuthorizedHandler:(void(^)())authorizedHandler
unAuthorizedHandler:(void(^)())unAuthorizedHandler{
SFSpeechRecognizerAuthorizationStatus authStatus = [SFSpeechRecognizer authorizationStatus];
if (authStatus == SFSpeechRecognizerAuthorizationStatusNotDetermined) {
//調用系統(tǒng)提供的權限訪問的方法
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) {
dispatch_async(dispatch_get_main_queue(), ^{
//授權成功后
authorizedHandler ? authorizedHandler() : nil;
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
//授權失敗后
unAuthorizedHandler ? unAuthorizedHandler() : nil;
});
}
}];
}else if (authStatus == SFSpeechRecognizerAuthorizationStatusAuthorized){
authorizedHandler ? authorizedHandler() : nil;
}else{
unAuthorizedHandler ? unAuthorizedHandler() : nil;
}
}
需要注意的是,調用
requestAuthorization
方法的block回調是在任意的子線程中進行的囤攀,如果你需要在授權成功后刷新UI的話宫纬,需要將對應的方法置于主線程中進行,筆者將上述方法默認在主線程中進行蝌衔。后續(xù)權限請求方法與此類似,不再贅述曹锨。-
在info.plist添加指定的配置信息剃允,如下所示:
媒體資料庫/Apple Music
- 導入頭文件@import MediaPlayer;
- 使用類MPMediaLibrary進行權限訪問斥废,代碼如下牡肉;
- (void)p_requestAppleMusicAccessWithAuthorizedHandler:(void(^)())authorizedHandler
unAuthorizedHandler:(void(^)())unAuthorizedHandler{
MPMediaLibraryAuthorizationStatus authStatus = [MPMediaLibrary authorizationStatus];
if (authStatus == MPMediaLibraryAuthorizationStatusNotDetermined) {
[MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus status) {
if (status == MPMediaLibraryAuthorizationStatusAuthorized) {
dispatch_async(dispatch_get_main_queue(), ^{
authorizedHandler ? authorizedHandler() : nil;
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
unAuthorizedHandler ? unAuthorizedHandler() : nil;
});
}
}];
}else if (authStatus == MPMediaLibraryAuthorizationStatusAuthorized){
authorizedHandler ? authorizedHandler() : nil;
}else{
unAuthorizedHandler ? unAuthorizedHandler() : nil;
}
}
- 在info.plist添加指定的配置信息,如下所示:
Siri
- 導入頭文件@import Intents;;
- 與其他權限不同的時跪另,使用Siri需要在Xcode中Capabilities打開Siri開關免绿,Xcode會自動生成一個xx.entitlements文件,若沒有打開該開關淌哟,項目運行時會報錯辽故。
- 實現(xiàn)代碼如下:
- (void)p_requestSiriAccessWithAuthorizedHandler:(void(^)())authorizedHandler
unAuthorizedHandler:(void(^)())unAuthorizedHandler{
INSiriAuthorizationStatus authStatus = [INPreferences siriAuthorizationStatus];
if (authStatus == INSiriAuthorizationStatusNotDetermined) {
[INPreferences requestSiriAuthorization:^(INSiriAuthorizationStatus status) {
if (status == INSiriAuthorizationStatusAuthorized) {
dispatch_async(dispatch_get_main_queue(), ^{
authorizedHandler ? authorizedHandler() : nil;
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
unAuthorizedHandler ? unAuthorizedHandler() : nil;
});
}
}];
}else if (authStatus == INSiriAuthorizationStatusAuthorized){
authorizedHandler ? authorizedHandler() : nil;
}else{
unAuthorizedHandler ? unAuthorizedHandler() : nil;
}
}
健康數(shù)據共享
- 導入頭文件@import HealthKit;
- 健康數(shù)據共享權限相對其他權限相對復雜一些誊垢,分為寫入和讀出權限.
- 在Xcode 8中的
info.plist
需要設置以下兩種權限:
1、Privacy - Health Update Usage Description
2殃饿、Privacy - Health Share Usage Description
- 具體實現(xiàn)代碼:
//設置寫入/共享的健康數(shù)據類型
- (NSSet *)typesToWrite {
HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
return [NSSet setWithObjects:stepType,distanceType, nil];
}
//設置讀寫以下為設置的權限類型:
- (NSSet *)typesToRead {
HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
return [NSSet setWithObjects:stepType,distanceType, nil];
}
//需要確定設備支持HealthKit
if ([HKHealthStore isHealthDataAvailable]) {
return;
}
HKHealthStore *healthStore = [[HKHealthStore alloc] init];
NSSet * typesToShare = [self typesToWrite];
NSSet * typesToRead = [self typesToRead];
[healthStore requestAuthorizationToShareTypes:typesToShare readTypes:typesToRead completion:^(BOOL success, NSError * _Nullable error) {
if (success) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Health has authorized!");
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Health has not authorized!");
});
}
}];
藍牙
- 需要導入頭文件@import CoreBluetooth;
- 藍牙的權限檢測相對其他會復雜一些,需要在代理中檢測藍牙狀態(tài);
- 獲取藍牙權限:
- (void)checkBluetoothAccess {
CBCentralManager *cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
CBManagerState state = [cbManager state];
if(state == CBManagerStateUnknown) {
NSLog(@"Unknown!");
}
else if(state == CBManagerStateUnauthorized) {
NSLog(@"Unauthorized!");
}
else {
NSLog(@"Granted!");
}
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
//這個代理方法會在藍牙權限狀態(tài)發(fā)生變化時被調用吭净,并且可以根據不同的狀態(tài)進行相應的修改UI或者數(shù)據訪問的操作寂殉。
}
- 請求藍牙權限
- (void)requestBluetoothAccess {
CBCentralManager *cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
//該方法會顯示用戶同意的彈窗
[cbManager scanForPeripheralsWithServices:nil options:nil];
}
住宅權限(HomeKit)
- 需導入頭文件@import HomeKit;
-
HomeKit
請求權限的方法如下:
- (void)requestHomeAccess {
self.homeManager = [[HMHomeManager alloc] init];
//當設置該代理方法后雷滋,會請求用戶權限
self.homeManager.delegate = self;
}
- (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager {
if (manager.homes.count > 0) {
// home的數(shù)量不為空晤斩,即表示用戶權限已通過
}
else {
__weak HMHomeManager *weakHomeManager = manager; // Prevent memory leak
[manager addHomeWithName:@"Test Home" completionHandler:^(HMHome *home, NSError *error) {
if (!error) {
//權限允許
}
else {
if (error.code == HMErrorCodeHomeAccessNotAuthorized) {
//權限不允許
}
else {
//處理請求產生的錯誤
}
}
if (home) {
[weakHomeManager removeHome:home completionHandler:^(NSError * _Nullable error) {
//移除Home
}];
}
}];
}
}
社交賬號體系權限
- 導入頭文件@import Accounts;
- 獲取對應的權限:
- (void)checkSocialAccountAuthorizationStatus:(NSString *)accountTypeIndentifier {
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *socialAccount = [accountStore accountTypeWithAccountTypeIdentifier:accountTypeIndentifier];
if ([socialAccount accessGranted]) {
NSLog(@"權限通過了");
}else{
NSLog(@"權限未通過澳泵!");
}
}
-
accountTypeIndentifier
可以是以下類型:
ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierTwitter NS_AVAILABLE(NA, 5_0);
ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierFacebook NS_AVAILABLE(NA, 6_0);
ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierSinaWeibo NS_AVAILABLE(NA, 6_0);
ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierTencentWeibo NS_AVAILABLE(NA, 7_0);
ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierLinkedIn NS_AVAILABLE(NA, NA);
- 請求對應的權限:
- (void)requestTwitterAccess {
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:accountTypeIdentifier];
[accountStore requestAccessToAccountsWithType: accountType options:nil completion:^(BOOL granted, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if(granted){
NSLog(@"授權通過了");
}else{
NSLog(@"授權未通過");
}
});
}];
}
活動與體能訓練記錄
- 導入頭文件@import CoreMotion;
- 具體實現(xiàn)代碼:
//訪問活動與體能訓練記錄
CMMotionActivityManager *cmManager = [[CMMotionActivityManager alloc] init];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[cmManager startActivityUpdatesToQueue:queue withHandler:^(CMMotionActivity *activity) {
//授權成功后兔辅,會進入Block方法內,授權失敗不會進入Block方法內
}];
廣告標識
- 導入頭文件@import AdSupport;
- 獲取廣告標識的權限狀態(tài):
BOOL isAuthorizedForAd = [[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled];
- 在使用
advertisingIdentifier
屬性前碰辅,必須調用上述方法判斷是否支持介时,如果上述方法返回值為NO
,則advertising ID
訪問將會受限循衰。
小結一下
- 通過以上兩篇文章的整理褐澎,有關iOS系統(tǒng)權限問題的處理基本上涵蓋完全了工三;
- 并不是所有的權限訪問都有顯式的調用方法,有些是在使用過程中進行訪問的奸鬓,比如
定位權限
段审、藍牙共享權限
、Homekit權限
抑淫、活動與體能訓練權限
姥闪,這些權限在使用時注意回調方法中的權限處理; -
HomeKit
催式、HealthKit
避归、Siri
需要開啟Capabilities
中的開關梳毙,即生成projectName.entitlements
文件; - 開源庫JLAuthorizationManager支持集成大部分常用的權限訪問账锹,便捷使用 welcome to pull request or star奸柬;
掃一掃下面的二維碼,歡迎關注我的個人微信公眾號攻城獅的動態(tài)(ID:iOSDevSkills)抱婉,可在微信公眾號進行留言懂从,更多精彩技術文章,期待您的加入侵贵!一起討論缘薛,一起成長宴胧!一起攻城獅!