再續iOS開發中的這些權限
阿新 • • 發佈:2017-07-05
tle store start 打開 帶來 tty 受限 bsp 不同的
前言 上篇文章iOS開發中的這些權限,你搞懂了嗎?介紹了一些常用權限的獲取和請求方法,知道這些方法的使用基本上可以搞定大部分應用的權限訪問的需求。但是,這些方法並不全面,不能涵蓋住所有權限訪問的方法。 So,筆者在介紹一下剩下的幾種權限的訪問方法和一些使用上的註意事項,希望能給大家的開發過程帶來一絲便利。 最後,筆者將經常使用的權限請求方法封裝開源庫JLAuthorizationManager送給大家,歡迎大家pull request 和 star~~ 權限 語音識別; 媒體資料庫/Apple Music; Siri; 健康數據共享; 藍牙; 住宅權限(HomeKit); 社交賬號體系權限; 活動與體能訓練記錄; 廣告標識; 語音識別 引入頭文件: @import Speech; 首先判斷當前應用所處的權限狀態,若當前狀態為NotDetermined(未確定),此時,需要調用系統提供的請求權限方法,同時也是觸發系統彈窗的所在點; 該權限涉及到的類為 SFSpeechRecognizer,具體代碼如下:- (void)p_requestSpeechRecognizerAccessWithAuthorizedHandler:(void(^)())authorizedHandler unAuthorizedHandler:(void(^)())unAuthorizedHandler{ SFSpeechRecognizerAuthorizationStatus authStatus = [SFSpeechRecognizer authorizationStatus]; if (authStatus == SFSpeechRecognizerAuthorizationStatusNotDetermined) {//調用系統提供的權限訪問的方法 [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的話,需要將對應的方法置於主線程中進行,筆者將上述方法默認在主線程中進行。後續權限請求方法與此類似,不再贅述。 在info.plist添加指定的配置信息,如下所示: Speech Recognizer 媒體資料庫/Apple Music [email protected] 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 [email protected] Intents;; 與其他權限不同的時,使用Siri需要在Xcode中Capabilities打開Siri開關,Xcode會自動生成一個xx.entitlements文件,若沒有打開該開關,項目運行時會報錯。 實現代碼如下: - (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; } } 健康數據共享 [email protected] HealthKit; 健康數據共享權限相對其他權限相對復雜一些,分為寫入和讀出權限. 在Xcode 8中的info.plist需要設置以下兩種權限: 1、Privacy - Health Update Usage Description 2、Privacy - Health Share Usage Description 具體實現代碼: //設置寫入/共享的健康數據類型 - (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!"); }); } }]; 藍牙 [email protected] CoreBluetooth; 藍牙的權限檢測相對其他會復雜一些,需要在代理中檢測藍牙狀態; 獲取藍牙權限: - (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 { //這個代理方法會在藍牙權限狀態發生變化時被調用,並且可以根據不同的狀態進行相應的修改UI或者數據訪問的操作。 } 請求藍牙權限 - (void)requestBluetoothAccess { CBCentralManager *cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; //該方法會顯示用戶同意的彈窗 [cbManager scanForPeripheralsWithServices:nil options:nil]; } 住宅權限(HomeKit) [email protected] HomeKit; HomeKit請求權限的方法如下: - (void)requestHomeAccess { self.homeManager = [[HMHomeManager alloc] init]; //當設置該代理方法後,會請求用戶權限 self.homeManager.delegate = self; } - (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager { if (manager.homes.count > 0) { // home的數量不為空,即表示用戶權限已通過 } 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 }]; } }]; } } 社交賬號體系權限 [email protected] 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(@"授權未通過"); } }); }]; } 活動與體能訓練記錄 [email protected] CoreMotion; 具體實現代碼: //訪問活動與體能訓練記錄 CMMotionActivityManager *cmManager = [[CMMotionActivityManager alloc] init]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [cmManager startActivityUpdatesToQueue:queue withHandler:^(CMMotionActivity *activity) { //授權成功後,會進入Block方法內,授權失敗不會進入Block方法內 }]; 廣告標識 [email protected] AdSupport; 獲取廣告標識的權限狀態: BOOL isAuthorizedForAd = [[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]; 在使用advertisingIdentifier屬性前,必須調用上述方法判斷是否支持,如果上述方法返回值為NO,則advertising ID訪問將會受限。 小結一下 通過以上兩篇文章的整理,有關iOS系統權限問題的處理基本上涵蓋完全了; 並不是所有的權限訪問都有顯式的調用方法,有些是在使用過程中進行訪問的,比如定位權限、藍牙共享權限、Homekit權限、活動與體能訓練權限,這些權限在使用時註意回調方法中的權限處理; HomeKit、HealthKit、Siri需要開啟Capabilities中的開關,即生成projectName.entitlements文件; 開源庫JLAuthorizationManager支持集成大部分常用的權限訪問,便捷使用 welcome to pull request or star;
再續iOS開發中的這些權限