作者:Jack_lin(公眾號ID:iOSDevSkills)
寫在前面
APP開發避免不開系統權限的問題,如何在APP以更加友好的方式向用戶展示系統權限,似乎也是開發過程中值得深思的一件事。
那如何提高APP獲取iOS系統權限的通過率呢?有以下幾種方式:1.在用戶打開APP時就向用戶請求權限;2.告知用戶授權權限後能夠獲得好處之後,再向用戶請求權限;3.在絕對必要的情況下才向用戶請求權限,例如:用戶訪問照片庫時請求訪問系統相冊權限;4.在展示系統權限的對話框前,先向用戶顯示自定義的對話框,若用戶選擇不允許,默認無操作,若用戶選擇允許,再展示系統對話框。
上述情況在開發過程中是經常遇到的,不同方式的選擇會影響最後用戶交互體驗。這一點感悟正是源於上一周工作遇到的問題:適配iOS10,如何獲取應用聯網權限用以管理系統對話框的顯示管理。當我把這個問題解決後,感覺有必要將常用的iOS系統權限做一個總結,以便後用。
權限分類
聯網權限
相冊權限
相機、麥克風權限
定位權限
推送權限
通訊錄權限
日歷、備忘錄權限
聯網權限
引入頭文件 @import CoreTelephony;
應用啟動後,檢測應用中是否有聯網權限
CTCellularData *cellularData = [[CTCellularData alloc]init]; cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state){ //獲取聯網狀態 switch (state) { case kCTCellularDataRestricted: NSLog(@"Restricrted"); break; case kCTCellularDataNotRestricted: NSLog(@"Not Restricted"); break; case kCTCellularDataRestrictedStateUnknown: NSLog(@"Unknown"); break; default: break; }; };
查詢應用是否有聯網功能
CTCellularData *cellularData = [[CTCellularData alloc]init]; CTCellularDataRestrictedState state = cellularData.restrictedState; switch (state) { case kCTCellularDataRestricted: NSLog(@"Restricrted"); break; case kCTCellularDataNotRestricted: NSLog(@"Not Restricted"); break; case kCTCellularDataRestrictedStateUnknown: NSLog(@"Unknown"); break; default: break; }
相冊權限
iOS 9.0之前
導入頭文件@import AssetsLibrary;
檢查是否有相冊權限
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus]; switch (status) { case ALAuthorizationStatusAuthorized: NSLog(@"Authorized"); break; case ALAuthorizationStatusDenied: NSLog(@"Denied"); break; case ALAuthorizationStatusNotDetermined: NSLog(@"not Determined"); break; case ALAuthorizationStatusRestricted: NSLog(@"Restricted"); break; default: break; }
相冊權限--iOS 8.0之後
導入頭文件@import Photos;
檢查是否有相冊權限
PHAuthorizationStatus photoAuthorStatus = [PHPhotoLibrary authorizationStatus]; switch (photoAuthorStatus) { case PHAuthorizationStatusAuthorized: NSLog(@"Authorized"); break; case PHAuthorizationStatusDenied: NSLog(@"Denied"); break; case PHAuthorizationStatusNotDetermined: NSLog(@"not Determined"); break; case PHAuthorizationStatusRestricted: NSLog(@"Restricted"); break; default: break; }
![Uploading 144446-b8aca7ba38c5f8c0_695906.png . . .]獲取相冊權限
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { if (status == PHAuthorizationStatusAuthorized) { NSLog(@"Authorized"); }else{ NSLog(@"Denied or Restricted"); } }];
相機和麥克風權限
導入頭文件@import AVFoundation;
檢查是否有相機或麥克風權限
AVAuthorizationStatus AVstatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];//相機權限 AVAuthorizationStatus AVstatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];//麥克風權限 switch (AVstatus) { case AVAuthorizationStatusAuthorized: NSLog(@"Authorized"); break; case AVAuthorizationStatusDenied: NSLog(@"Denied"); break; case AVAuthorizationStatusNotDetermined: NSLog(@"not Determined"); break; case AVAuthorizationStatusRestricted: NSLog(@"Restricted"); break; default: break; }
獲取相機或麥克風權限
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {//相機權限 if (granted) { NSLog(@"Authorized"); }else{ NSLog(@"Denied or Restricted"); } }]; [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {//麥克風權限 if (granted) { NSLog(@"Authorized"); }else{ NSLog(@"Denied or Restricted"); } }];
定位權限
導入頭文件@import CoreLocation;
由於iOS8.0之後定位方法的改變,需要在info.plist中進行配置;
配置文件
檢查是否有定位權限
BOOL isLocation = [CLLocationManager locationServicesEnabled]; if (!isLocation) { NSLog(@"not turn on the location"); } CLAuthorizationStatus CLstatus = [CLLocationManager authorizationStatus]; switch (CLstatus) { case kCLAuthorizationStatusAuthorizedAlways: NSLog(@"Always Authorized"); break; case kCLAuthorizationStatusAuthorizedWhenInUse: NSLog(@"AuthorizedWhenInUse"); break; case kCLAuthorizationStatusDenied: NSLog(@"Denied"); break; case kCLAuthorizationStatusNotDetermined: NSLog(@"not Determined"); break; case kCLAuthorizationStatusRestricted: NSLog(@"Restricted"); break; default: break; }
獲取定位權限
CLLocationManager *manager = [[CLLocationManager alloc] init]; [manager requestAlwaysAuthorization];//一直獲取定位信息 [manager requestWhenInUseAuthorization];//使用的時候獲取定位信息
在代理方法中查看權限是否改變
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{ switch (status) { case kCLAuthorizationStatusAuthorizedAlways: NSLog(@"Always Authorized"); break; case kCLAuthorizationStatusAuthorizedWhenInUse: NSLog(@"AuthorizedWhenInUse"); break; case kCLAuthorizationStatusDenied: NSLog(@"Denied"); break; case kCLAuthorizationStatusNotDetermined: NSLog(@"not Determined"); break; case kCLAuthorizationStatusRestricted: NSLog(@"Restricted"); break; default: break; } }
推送權限
檢查是否有通訊權限
UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings]; switch (settings.types) { case UIUserNotificationTypeNone: NSLog(@"None"); break; case UIUserNotificationTypeAlert: NSLog(@"Alert Notification"); break; case UIUserNotificationTypeBadge: NSLog(@"Badge Notification"); break; case UIUserNotificationTypeSound: NSLog(@"sound Notification'"); break; default: break; }
獲取推送權限
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil]; [[UIApplication sharedApplication] registerUserNotificationSettings:setting];
通訊錄權限
iOS 9.0之前
導入頭文件 @import AddressBook;
檢查是否有通訊錄權限
ABAuthorizationStatus ABstatus = ABAddressBookGetAuthorizationStatus(); switch (ABstatus) { case kABAuthorizationStatusAuthorized: NSLog(@"Authorized"); break; case kABAuthorizationStatusDenied: NSLog(@"Denied'"); break; case kABAuthorizationStatusNotDetermined: NSLog(@"not Determined"); break; case kABAuthorizationStatusRestricted: NSLog(@"Restricted"); break; default: break; }
獲取通訊錄權限
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL); ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { if (granted) { NSLog(@"Authorized"); CFRelease(addressBook); }else{ NSLog(@"Denied or Restricted"); } });
iOS 9.0及以後
導入頭文件 @import Contacts;
檢查是否有通訊錄權限
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; switch (status) { case CNAuthorizationStatusAuthorized: { NSLog(@"Authorized:"); } break; case CNAuthorizationStatusDenied:{ NSLog(@"Denied"); } break; case CNAuthorizationStatusRestricted:{ NSLog(@"Restricted"); } break; case CNAuthorizationStatusNotDetermined:{ NSLog(@"NotDetermined"); } break; }
獲取通訊錄權限
CNContactStore *contactStore = [[CNContactStore alloc] init]; [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { if (granted) { NSLog(@"Authorized"); }else{ NSLog(@"Denied or Restricted"); } }];
日歷、備忘錄權限
導入頭文件
檢查是否有日歷或者備忘錄權限
typedef NS_ENUM(NSUInteger, EKEntityType) { EKEntityTypeEvent,//日歷 EKEntityTypeReminder //備忘 };
EKAuthorizationStatus EKstatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent]; switch (EKstatus) { case EKAuthorizationStatusAuthorized: NSLog(@"Authorized"); break; case EKAuthorizationStatusDenied: NSLog(@"Denied'"); break; case EKAuthorizationStatusNotDetermined: NSLog(@"not Determined"); break; case EKAuthorizationStatusRestricted: NSLog(@"Restricted"); break; default: break; }
獲取日歷或備忘錄權限
EKEventStore *store = [[EKEventStore alloc]init]; [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) { if (granted) { NSLog(@"Authorized"); }else{ NSLog(@"Denied or Restricted"); } }];
最後一點
素有獲取權限的方法,多用於用戶第一次操作應用,iOS 8.0之後,將這些設置都整合在一起,並且可以開啟或關閉相應的權限。所有的權限都可以通過下面的方法打開:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
上述的權限多為經常用到的權限,當然不會很全面,大家如有需要其他的權限,可以在下方評論,我會及時加上去的。
希望這篇文章能夠給大家的開發帶來一些便利。