[續(xù)]iOS開發(fā)中的這些權(quán)限,你搞懂了嗎?

瘋狂

前言

  • 上篇文章iOS開發(fā)中的這些權(quán)限,你搞懂了嗎?介紹了一些常用權(quán)限的獲取和請求方法,知道這些方法的使用基本上可以搞定大部分應(yīng)用的權(quán)限訪問的需求。但是,這些方法并不全面,不能涵蓋住所有權(quán)限訪問的方法。

  • So,筆者在介紹一下剩下的幾種權(quán)限的訪問方法和一些使用上的注意事項,希望能給大家的開發(fā)過程帶來一絲便利。

  • 最后,筆者將經(jīng)常使用的權(quán)限請求方法封裝開源庫JLAuthorizationManager送給大家,歡迎大家pull requeststar~~
    Objective-C版本
    Swift版本

權(quán)限

  • 語音識別;
  • 媒體資料庫/Apple Music;
  • Siri;
  • 健康數(shù)據(jù)共享;
  • 藍牙;
  • 住宅權(quán)限(HomeKit);
  • 社交賬號體系權(quán)限;
  • 活動與體能訓(xùn)練記錄;
  • 廣告標(biāo)識;

語音識別

  • 引入頭文件: @import Speech;
  • 首先判斷當(dāng)前應(yīng)用所處的權(quán)限狀態(tài),若當(dāng)前狀態(tài)為NotDetermined(未確定),此時,需要調(diào)用系統(tǒng)提供的請求權(quán)限方法,同時也是觸發(fā)系統(tǒng)彈窗的所在點;
  • 該權(quán)限涉及到的類為** SFSpeechRecognizer**,具體代碼如下:
- (void)p_requestSpeechRecognizerAccessWithAuthorizedHandler:(void(^)())authorizedHandler
                                         unAuthorizedHandler:(void(^)())unAuthorizedHandler{
    
    SFSpeechRecognizerAuthorizationStatus authStatus = [SFSpeechRecognizer authorizationStatus];
    if (authStatus == SFSpeechRecognizerAuthorizationStatusNotDetermined) {
         //調(diào)用系統(tǒng)提供的權(quán)限訪問的方法
        [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
            if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) {
                dispatch_async(dispatch_get_main_queue(), ^{
                     //授權(quán)成功后
                    authorizedHandler ? authorizedHandler() : nil;
                });
            }else{
                dispatch_async(dispatch_get_main_queue(), ^{
                    //授權(quán)失敗后
                    unAuthorizedHandler ? unAuthorizedHandler() : nil;
                });
            }
        }];
        
    }else if (authStatus == SFSpeechRecognizerAuthorizationStatusAuthorized){
        authorizedHandler ? authorizedHandler() : nil;
    }else{
        unAuthorizedHandler ? unAuthorizedHandler() : nil;
    }
}
  • 需要注意的是,調(diào)用requestAuthorization方法的block回調(diào)是在任意的子線程中進行的,如果你需要在授權(quán)成功后刷新UI的話,需要將對應(yīng)的方法置于主線程中進行,筆者將上述方法默認(rèn)在主線程中進行。后續(xù)權(quán)限請求方法與此類似,不再贅述。

  • info.plist添加指定的配置信息,如下所示:

    Speech Recognizer

媒體資料庫/Apple Music

  • 導(dǎo)入頭文件@import MediaPlayer;
  • 使用類MPMediaLibrary進行權(quán)限訪問,代碼如下;
- (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添加指定的配置信息,如下所示:
    Media

Siri

  • 導(dǎo)入頭文件@import Intents;;
  • 與其他權(quán)限不同的時,使用Siri需要在Xcode中Capabilities打開Siri開關(guān),Xcode會自動生成一個xx.entitlements文件,若沒有打開該開關(guān),項目運行時會報錯。
  • 實現(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ù)據(jù)共享

  • 導(dǎo)入頭文件@import HealthKit;
  • 健康數(shù)據(jù)共享權(quán)限相對其他權(quán)限相對復(fù)雜一些,分為寫入和讀出權(quán)限.
  • 在Xcode 8中的info.plist需要設(shè)置以下兩種權(quán)限:
1、Privacy - Health Update Usage Description
2、Privacy - Health Share Usage Description
  • 具體實現(xiàn)代碼:
//設(shè)置寫入/共享的健康數(shù)據(jù)類型
- (NSSet *)typesToWrite {
    HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
    return [NSSet setWithObjects:stepType,distanceType, nil];
}

//設(shè)置讀寫以下為設(shè)置的權(quán)限類型:
- (NSSet *)typesToRead {
   HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
    return [NSSet setWithObjects:stepType,distanceType, nil];
}

//需要確定設(shè)備支持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!");
            });
        }
    }];

藍牙

  • 需要導(dǎo)入頭文件@import CoreBluetooth;
  • 藍牙的權(quán)限檢測相對其他會復(fù)雜一些,需要在代理中檢測藍牙狀態(tài);
  • 獲取藍牙權(quán)限:
- (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 {
//這個代理方法會在藍牙權(quán)限狀態(tài)發(fā)生變化時被調(diào)用,并且可以根據(jù)不同的狀態(tài)進行相應(yīng)的修改UI或者數(shù)據(jù)訪問的操作。
}

  • 請求藍牙權(quán)限
- (void)requestBluetoothAccess {
    CBCentralManager *cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
//該方法會顯示用戶同意的彈窗
    [cbManager scanForPeripheralsWithServices:nil options:nil];
}

住宅權(quán)限(HomeKit)

  • 需導(dǎo)入頭文件@import HomeKit;
  • HomeKit請求權(quán)限的方法如下:
- (void)requestHomeAccess {
    self.homeManager = [[HMHomeManager alloc] init];
//當(dāng)設(shè)置該代理方法后,會請求用戶權(quán)限
    self.homeManager.delegate = self;
}

- (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager {
    if (manager.homes.count > 0) {
        // home的數(shù)量不為空,即表示用戶權(quán)限已通過
    }
    else {
        __weak HMHomeManager *weakHomeManager = manager; // Prevent memory leak
        [manager addHomeWithName:@"Test Home" completionHandler:^(HMHome *home, NSError *error) {
            
            if (!error) {
               //權(quán)限允許
            }
            else {
                if (error.code == HMErrorCodeHomeAccessNotAuthorized) {
                   //權(quán)限不允許
                }
                else {
                    //處理請求產(chǎn)生的錯誤
                }
            }
            
            if (home) {
                [weakHomeManager removeHome:home completionHandler:^(NSError * _Nullable error) {
                    //移除Home
                }];
            }
        }];
    }
}

社交賬號體系權(quán)限

  • 導(dǎo)入頭文件@import Accounts;
  • 獲取對應(yīng)的權(quán)限:
- (void)checkSocialAccountAuthorizationStatus:(NSString *)accountTypeIndentifier {

    ACAccountStore *accountStore = [[ACAccountStore alloc] init];
    ACAccountType *socialAccount = [accountStore accountTypeWithAccountTypeIdentifier:accountTypeIndentifier];
    if ([socialAccount accessGranted]) {
        NSLog(@"權(quán)限通過了");
    }else{
         NSLog(@"權(quán)限未通過!");
 }
}
  • 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);
  • 請求對應(yīng)的權(quán)限:
- (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(@"授權(quán)通過了");
            }else{
                 NSLog(@"授權(quán)未通過");
            }
        });
    }];
}

活動與體能訓(xùn)練記錄

  • 導(dǎo)入頭文件@import CoreMotion;
  • 具體實現(xiàn)代碼:
//訪問活動與體能訓(xùn)練記錄
    CMMotionActivityManager *cmManager = [[CMMotionActivityManager alloc] init];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    [cmManager startActivityUpdatesToQueue:queue withHandler:^(CMMotionActivity *activity) {
        
        //授權(quán)成功后,會進入Block方法內(nèi),授權(quán)失敗不會進入Block方法內(nèi)
    }];

廣告標(biāo)識

  • 導(dǎo)入頭文件@import AdSupport;
  • 獲取廣告標(biāo)識的權(quán)限狀態(tài):
 BOOL isAuthorizedForAd = [[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled];
  • 在使用advertisingIdentifier屬性前,必須調(diào)用上述方法判斷是否支持,如果上述方法返回值為NO,則advertising ID訪問將會受限。

小結(jié)一下

  • 通過以上兩篇文章的整理,有關(guān)iOS系統(tǒng)權(quán)限問題的處理基本上涵蓋完全了;
  • 并不是所有的權(quán)限訪問都有顯式的調(diào)用方法,有些是在使用過程中進行訪問的,比如定位權(quán)限藍牙共享權(quán)限、Homekit權(quán)限、活動與體能訓(xùn)練權(quán)限,這些權(quán)限在使用時注意回調(diào)方法中的權(quán)限處理;
  • HomeKitHealthKit、Siri需要開啟Capabilities中的開關(guān),即生成projectName.entitlements文件;
  • 開源庫JLAuthorizationManager支持集成大部分常用的權(quán)限訪問,便捷使用 welcome to pull request or star;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容