iOS開發(fā)中權限再度梳理

瘋狂

前言

開源庫JLAuthorizationManager :
Objective-C版本
Swift版本

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

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

  • 最后烘豹,筆者將經常使用的權限請求方法封裝開源庫JLAuthorizationManager送給大家携悯,歡迎大家pull requeststar~~

權限

  • 語音識別筷笨;
  • 媒體資料庫/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添加指定的配置信息剃允,如下所示:

    Speech Recognizer

媒體資料庫/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添加指定的配置信息,如下所示:
    Media

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)抱婉,可在微信公眾號進行留言懂从,更多精彩技術文章,期待您的加入侵贵!一起討論缘薛,一起成長宴胧!一起攻城獅!

公眾號
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末乞娄,一起剝皮案震驚了整個濱河市仪或,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蕾域,老刑警劉巖到旦,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件添忘,死亡現(xiàn)場離奇詭異,居然都是意外死亡懈万,警方通過查閱死者的電腦和手機靶病,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門娄周,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人裳涛,你說我怎么就攤上這事众辨。” “怎么了郊闯?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵团赁,是天一觀的道長谨履。 經常有香客問我,道長怀挠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任嫌变,我火速辦了婚禮躬它,結果婚禮上冯吓,老公的妹妹穿的比我還像新娘疮跑。我一直安慰自己,他們只是感情好失尖,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布掀潮。 她就那樣靜靜地躺著琼富,像睡著了一般。 火紅的嫁衣襯著肌膚如雪薯鼠。 梳的紋絲不亂的頭發(fā)上械蹋,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天哗戈,我揣著相機與錄音,去河邊找鬼暇仲。 笑死副渴,一個胖子當著我的面吹牛,可吹牛的內容都是我干的斥滤。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼顶掉,長吁一口氣:“原來是場噩夢啊……” “哼挑胸!你這毒婦竟也來了茬贵?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤老充,失蹤者是張志新(化名)和其女友劉穎啡浊,沒想到半個月后胶背,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡涂籽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年评雌,在試婚紗的時候發(fā)現(xiàn)自己被綠了直焙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奔誓。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖和措,靈堂內的尸體忽然破棺而出蜕煌,到底是詐尸還是另有隱情,我是刑警寧澤贫母,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布腺劣,位于F島的核電站,受9級特大地震影響籍铁,放射性物質發(fā)生泄漏趾断。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一耻警、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甘穿,春花似錦、人聲如沸秸滴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至误债,卻和暖如春妄迁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背箫老。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工槽惫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人仿耽。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像各薇,于是被迫代替她去往敵國和親项贺。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內容