1、写在前面

  • APP开发避免不开系统权限的问题,如何在APP以更加友好的方式向用户展示系统权限,似乎也是开发过程中值得深思的一件事;
  • 那如何提高APP获取iOS系统权限的通过率呢?有以下几种方式:
    • 1.在用户打开APP时就向用户请求权限;
    • 2.告知用户授权权限后能够获得好处之后,再向用户请求权限;
    • 3.在绝对必要的情况下才向用户请求权限,例如:用户访问照片库时请求访问系统相册权限;
    • 4.在展示系统权限的对话框前,先向用户显示自定义的对话框,若用户选择不允许,默认无操作,若用户选择允许,再展示系统对话框。
  • 上述情况在开发过程中是经常遇到的,不同方式的选择会影响最后用户交互体验。

2、权限分类

  • 2.1 联网权限

    • 引入头文件 @import CoreTelephony;
    • 应用启动后,检测应用中是否有联网权限
    1. CTCellularData *cellularData = [[CTCellularData alloc]init];
    2. cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state){
    3. //获取联网状态
    4. switch (state) {
    5. case kCTCellularDataRestricted:
    6. NSLog(@"Restricrted");
    7. break;
    8. case kCTCellularDataNotRestricted:
    9. NSLog(@"Not Restricted");
    10. break;
    11. case kCTCellularDataRestrictedStateUnknown:
    12. NSLog(@"Unknown");
    13. break;
    14. default:
    15. break;
    16. };
    17. };
    • 查询应用是否有联网功能
    1. CTCellularData *cellularData = [[CTCellularData alloc]init];
    2. CTCellularDataRestrictedState state = cellularData.restrictedState;
    3. switch (state) {
    4. case kCTCellularDataRestricted:
    5. NSLog(@"Restricrted");
    6. break;
    7. case kCTCellularDataNotRestricted:
    8. NSLog(@"Not Restricted");
    9. break;
    10. case kCTCellularDataRestrictedStateUnknown:
    11. NSLog(@"Unknown");
    12. break;
    13. default:
    14. break;
    15. }
  • 2.2 相册权限

    • --iOS 9.0之前
    • 导入头文件 #import <AssetsLibrary/AssetsLibrary.h>
    • 检查是否有相册权限
    1. ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
    2. switch (status) {
    3. case ALAuthorizationStatusAuthorized:
    4. NSLog(@"Authorized");
    5. break;
    6. case ALAuthorizationStatusDenied:
    7. NSLog(@"Denied");
    8. break;
    9. case ALAuthorizationStatusNotDetermined:
    10. NSLog(@"not Determined");
    11. break;
    12. case ALAuthorizationStatusRestricted:
    13. NSLog(@"Restricted");
    14. break;
    15. default:
    16. break;
    17. }
  • 相册权限--iOS 8.0之后

    • 导入头文件 #import <Photos/Photos.h>
    • 检查是否有相册权限
    1. PHAuthorizationStatus photoAuthorStatus = [PHPhotoLibrary authorizationStatus];
    2. switch (photoAuthorStatus) {
    3. case PHAuthorizationStatusAuthorized:
    4. NSLog(@"Authorized");
    5. break;
    6. case PHAuthorizationStatusDenied:
    7. NSLog(@"Denied");
    8. break;
    9. case PHAuthorizationStatusNotDetermined:
    10. NSLog(@"not Determined");
    11. break;
    12. case PHAuthorizationStatusRestricted:
    13. NSLog(@"Restricted");
    14. break;
    15. default:
    16. break;
    17. }
    18. [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
    19. if (status == PHAuthorizationStatusAuthorized) {
    20. NSLog(@"Authorized");
    21. }
    22. else {
    23. NSLog(@"Denied or Restricted");
    24. }
    25. }];
  • 2.3 相机和麦克风权限

    • 导入头文件#import <AVFoundation/AVFoundation.h>
    • 检查是否有相机或麦克风权限
    1. AVAuthorizationStatus AVstatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];//相机权限
    2. AVAuthorizationStatus AVstatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];//麦克风权限
    3. switch (AVstatus) {
    4. case AVAuthorizationStatusAuthorized:
    5. NSLog(@"Authorized");
    6. break;
    7. case AVAuthorizationStatusDenied:
    8. NSLog(@"Denied");
    9. break;
    10. case AVAuthorizationStatusNotDetermined:
    11. NSLog(@"not Determined");
    12. break;
    13. case AVAuthorizationStatusRestricted:
    14. NSLog(@"Restricted");
    15. break;
    16. default:
    17. break;
    18. }
    • 获取相机或麦克风权限
    1. [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {//相机权限
    2. if (granted) {
    3. NSLog(@"Authorized");
    4. }
    5. else {
    6. NSLog(@"Denied or Restricted");
    7. }
    8. }];
    9. [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {//麦克风权限
    10. if (granted) {
    11. NSLog(@"Authorized");
    12. }
    13. else {
    14. NSLog(@"Denied or Restricted");
    15. }
    16. }];
  • 2.4 定位权限

    • 导入头文件#import <CoreLocation/CoreLocation.h>
    • 由于iOS8.0之后定位方法的改变,需要在info.plist中进行配置;
    • 检查是否有定位权限
    1. BOOL isLocation = [CLLocationManager locationServicesEnabled];
    2. if (!isLocation) {
    3. NSLog(@"not turn on the location");
    4. }
    5. CLAuthorizationStatus CLstatus = [CLLocationManager authorizationStatus];
    6. switch (CLstatus) {
    7. case kCLAuthorizationStatusAuthorizedAlways:
    8. NSLog(@"Always Authorized");
    9. break;
    10. case kCLAuthorizationStatusAuthorizedWhenInUse:
    11. NSLog(@"AuthorizedWhenInUse");
    12. break;
    13. case kCLAuthorizationStatusDenied:
    14. NSLog(@"Denied");
    15. break;
    16. case kCLAuthorizationStatusNotDetermined:
    17. NSLog(@"not Determined");
    18. break;
    19. case kCLAuthorizationStatusRestricted:
    20. NSLog(@"Restricted");
    21. break;
    22. default:
    23. break;
    24. }
    • 获取定位权限
    1. CLLocationManager *manager = [[CLLocationManager alloc] init];
    2. [manager requestAlwaysAuthorization];//一直获取定位信息
    3. [manager requestWhenInUseAuthorization];//使用的时候获取定位信息
    • 在代理方法中查看权限是否改变
    1. - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{
    2. switch (status) {
    3. case kCLAuthorizationStatusAuthorizedAlways:
    4. NSLog(@"Always Authorized");
    5. break;
    6. case kCLAuthorizationStatusAuthorizedWhenInUse:
    7. NSLog(@"AuthorizedWhenInUse");
    8. break;
    9. case kCLAuthorizationStatusDenied:
    10. NSLog(@"Denied");
    11. break;
    12. case kCLAuthorizationStatusNotDetermined:
    13. NSLog(@"not Determined");
    14. break;
    15. case kCLAuthorizationStatusRestricted:
    16. NSLog(@"Restricted");
    17. break;
    18. default:
    19. break;
    20. }
    21. }
  • 2.5 推送权限

    • 检查是否有通讯权限
    1. UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings];
    2. switch (settings.types) {
    3. case UIUserNotificationTypeNone:
    4. NSLog(@"None");
    5. break;
    6. case UIUserNotificationTypeAlert:
    7. NSLog(@"Alert Notification");
    8. break;
    9. case UIUserNotificationTypeBadge:
    10. NSLog(@"Badge Notification");
    11. break;
    12. case UIUserNotificationTypeSound:
    13. NSLog(@"sound Notification'");
    14. break;
    15. default:
    16. break;
    17. }
    • 获取推送权限
    1. UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil];
    2. [[UIApplication sharedApplication] registerUserNotificationSettings:setting];
  • 2.6 通讯录权限

    • iOS9.0之前
    • 导入头文件#import <AddressBook/AddressBook.h>
    • 检查是否有通讯录权限
    1. ABAuthorizationStatus ABstatus = ABAddressBookGetAuthorizationStatus();
    2. switch (ABstatus) {
    3. case kABAuthorizationStatusAuthorized:
    4. NSLog(@"Authorized");
    5. break;
    6. case kABAuthorizationStatusDenied:
    7. NSLog(@"Denied'");
    8. break;
    9. case kABAuthorizationStatusNotDetermined:
    10. NSLog(@"not Determined");
    11. break;
    12. case kABAuthorizationStatusRestricted:
    13. NSLog(@"Restricted");
    14. break;
    15. default:
    16. break;
    17. }
    • 获取通讯录权限
    1. ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
    2. ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
    3. if (granted) {
    4. NSLog(@"Authorized");
    5. CFRelease(addressBook);
    6. }
    7. else {
    8. NSLog(@"Denied or Restricted");
    9. }
    10. });
    • iOS9.0及以后
    • 导入头文件#import <Contacts/Contacts.h>
    • 检查是否有通讯录权限
    1. CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    2. switch (status) {
    3. case CNAuthorizationStatusAuthorized: {
    4. NSLog(@"Authorized:");
    5. }
    6. break;
    7. case CNAuthorizationStatusDenied:{
    8. NSLog(@"Denied");
    9. }
    10. break;
    11. case CNAuthorizationStatusRestricted:{
    12. NSLog(@"Restricted");
    13. }
    14. break;
    15. case CNAuthorizationStatusNotDetermined:{
    16. NSLog(@"NotDetermined");
    17. }
    18. break;
    19. }
    • 获取通讯录权限
    1. CNContactStore *contactStore = [[CNContactStore alloc] init];
    2. [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
    3. if (granted) {
    4. NSLog(@"Authorized");
    5. }
    6. else {
    7. NSLog(@"Denied or Restricted");
    8. }
    9. }];
  • 2.7 日历、备忘录权限

    • 导入头文件
    • 检查是否有日历或者备忘录权限
    1. typedef NS_ENUM(NSUInteger, EKEntityType) {
    2. EKEntityTypeEvent,//日历
    3. EKEntityTypeReminder //备忘
    4. };
    5. EKAuthorizationStatus EKstatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
    6. switch (EKstatus) {
    7. case EKAuthorizationStatusAuthorized:
    8. NSLog(@"Authorized");
    9. break;
    10. case EKAuthorizationStatusDenied:
    11. NSLog(@"Denied'");
    12. break;
    13. case EKAuthorizationStatusNotDetermined:
    14. NSLog(@"not Determined");
    15. break;
    16. case EKAuthorizationStatusRestricted:
    17. NSLog(@"Restricted");
    18. break;
    19. default:
    20. break;
    21. }
    • 获取日历或备忘录权限
    1. EKEventStore *store = [[EKEventStore alloc]init];
    2. [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
    3. if (granted) {
    4. NSLog(@"Authorized");
    5. }else{
    6. NSLog(@"Denied or Restricted");
    7. }
    8. }];

3、最后一点

  • 所有获取权限的方法,多用于用户第一次操作应用,iOS 8.0之后,将这些设置都整合在一起,并且可以开启或关闭相应的权限。所有的权限都可以通过下面的方法打开:
  1. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];

iOS应用开发权限请求处理的更多相关文章

  1. iOS开发-iOS 10 由于权限问题导致崩溃的那些坑

     iOS开发-iOS 10 由于权限问题导致崩溃的那些坑 6月份的WWDC大会结束有一段时间了,相信很多开发者也是在努力工作的闲时用着Xcode8 Beta版学习着新的特性吧. 使用Xcode8写自己 ...

  2. iOS 10 开发问题总结

    兼容iOS 10 资料整理笔记   1.Notification(通知) 自从Notification被引入之后,苹果就不断的更新优化,但这些更新优化只是小打小闹,直至现在iOS 10开始真正的进行大 ...

  3. iOS蓝牙开发(二)蓝牙相关基础知识

    原文链接: http://liuyanwei.jumppo.com/2015/07/17/ios-BLE-1.html iOS蓝牙开发(一)蓝牙相关基础知识: 蓝牙常见名称和缩写 MFI ====== ...

  4. web前端开发与iOS终端开发的异同[转]

    * {-webkit-tap-highlight-color: rgba(0,0,0,0);}html {-webkit-text-size-adjust: none;}body {font-fami ...

  5. iOS蓝牙开发(4.0)详解

    最近由于项目需要, 一直在研究蓝牙4.0,在这儿分享给大家, 望共同进步. 一.关于蓝牙开发的一些重要的理论概念: 1.当前ios中开发蓝牙所运用的系统库是<CoreBluetooth/Core ...

  6. iOS 11开发教程(九)iOS11数据线连接真机测试

    iOS 11开发教程(九)iOS11数据线连接真机测试 在Xcode 7.0之后,苹果公司在开发许可权限上做了很多的改变,在测试App方面取消了一些限制.在Xcode7.0之前的版本,苹果公司只向注册 ...

  7. Web前端开发与iOS终端开发的异同

    语言 前端和终端作为面向用户端的程序,有个共同特点:需要依赖用户机器的运行环境,所以开发语言基本上是没有选择的,不像后台想用什么就用什么,iOS只能用Objective-C,前端只能javascrip ...

  8. iOS 蓝牙开发详解

    目前iOS智能硬件的开发交互方式主要分为两种,一种是基于低功耗的蓝牙4.0技术(由于耗电低,也称作为BLE(Bluetooth Low Energy))对应iOS的框架为CoreBluetooth,另 ...

  9. 中文 iOS/Mac 开发博客列表

    中文 iOS/Mac 开发博客列表 博客地址 RSS地址 OneV's Den http://onevcat.com/atom.xml 一只魔法师的工坊 http://blog.ibireme.com ...

随机推荐

  1. Reids 批量删除有相同前缀的keys

    redis-cli 登录redis 我一般使用 redis-cli 登录redis ,但是进去后会提示" Redis (error) NOAUTH Authentication requir ...

  2. Python实现七牛云视频播放

    这篇文章是使用Python的Web框架Django Rest Framework来提供视频相关的api接口,主要功能包括视频上传.视频转码.视频访问授权.删除视频文件.视频截图功能. 七牛云上的基本概 ...

  3. 运动函数封装(js)

    // 运动函数 function starMove(obj,json,fnEnd){ clearInterval(obj.timer); obj.timer  = setInterval(functi ...

  4. What is _MainTex_ST ?

    [What is _MainTex_ST ?] 在Unity自带的Unlit/Texture中,有引用到float4 _MainTex_ST,如下: // Unlit shader. Simplest ...

  5. ubuntu 重启显卡报错 nvidia

    1.我装玩显卡以后重启报错了 解决了5个小时才解决,先贴个当时报错的图 第一个图是没有加nomodeset 出先的 当你出现第二个图片的时候证明你离成功不远了 从头开始: 1.开机,出现 ubuntu ...

  6. CS的项目管理是基于多租户理念设计

    1.创建项目 http://xxx.xxx.xx.xx:8080/client/api?command=createProject&response=json&sessionkey=8 ...

  7. 10-stack

    c++ stl栈stack介绍 C++ Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,——也就是说实现了一个先进后出(FILO)的数据结构. c++ stl栈stack的头文件 ...

  8. Webdings和Wingdings字符码对应表

    刚才研究动网论坛代码,发现一个页面提示标记 i 感觉很神奇,看了半天才明白原来是一种叫“Webdings”的字体,其实很简单,只需要<font face='webdings' size=&quo ...

  9. zigbee之IAR环境搭建

    注册机第一个要选择: 为什么? 之前说CC2530是支持zigbee协议的无线芯片,其实它是这款硬件上有一个支持zigbee协议的无线电路,不仅有这款电路,而且还有一块cpu电路,它就是8051cpu ...

  10. MYSQL隐式类型转换

    MYSQL隐式类型转换 关于官方文档中的理解大致是: 如果两个参数比较,有至少一个NULL,结果就是NULL,除了是用NULL<=>NULL 会返回1.不做类型转换 两个参数都是字符串,按 ...