1、写在前面

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

2、权限分类

  • 2.1 联网权限

    • 引入头文件 @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;
    }
  • 2.2 相册权限

    • --iOS 9.0之前
    • 导入头文件 #import <AssetsLibrary/AssetsLibrary.h>
    • 检查是否有相册权限
     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/Photos.h>
    • 检查是否有相册权限
    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;
    } [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
    if (status == PHAuthorizationStatusAuthorized) {
    NSLog(@"Authorized");
    }
    else {
    NSLog(@"Denied or Restricted");
    }
    }];
  • 2.3 相机和麦克风权限

    • 导入头文件#import <AVFoundation/AVFoundation.h>
    • 检查是否有相机或麦克风权限
    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");
    }
    }];
  • 2.4 定位权限

    • 导入头文件#import <CoreLocation/CoreLocation.h>
    • 由于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;
    }
    }
  • 2.5 推送权限

    • 检查是否有通讯权限
    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];
  • 2.6 通讯录权限

    • iOS9.0之前
    • 导入头文件#import <AddressBook/AddressBook.h>
    • 检查是否有通讯录权限
    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");
    }
    });
    • iOS9.0及以后
    • 导入头文件#import <Contacts/Contacts.h>
    • 检查是否有通讯录权限
    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");
    }
    }];
  • 2.7 日历、备忘录权限

    • 导入头文件
    • 检查是否有日历或者备忘录权限
    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");
    }
    }];

3、最后一点

  • 所有获取权限的方法,多用于用户第一次操作应用,iOS 8.0之后,将这些设置都整合在一起,并且可以开启或关闭相应的权限。所有的权限都可以通过下面的方法打开:
[[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. Mysql事务及行级锁

    事务隔离级别 数据库事务隔离级别,只是针对一个事务能不能读取其它事务的中间结果. Read Uncommitted (读取未提交内容) 在该隔离级别,所有事务都可以看到其他未提交事务的执行结果.本隔离 ...

  2. 解决OpenFeign默认无法上传文件的问题

    前言 最近在项目中使用OpenFeign时,发现其不支持文件上传功能.网上找了很多资料,最后找到feign-form和feign-form-spring的解决方案.但其默认只支持单文件上传,不支持多文 ...

  3. 【LA3713 训练指南】宇航员分组 【2-sat】

    题意 有A,B,C三个任务要分配给n个宇航员,其中每个宇航员恰好要分配一个任务.设所有n个宇航员的平均年龄为x,只有年龄大于或等于x的宇航员才能分配任务A:只有年龄严格小于x的宇航员才能分配任务B,而 ...

  4. Unity Remote 5 使用

    从哪里下载,我是从应用商店里下载的 一. Android版 首先应该确保安装了最新的 Android SDK(这对于在设备上设置端口转发非常必要). 然后,使用 USB 连接线连接设备与电脑,并启动U ...

  5. Linux环境(Centos) 安装mysql

    MariaDB是mysql的开源分支,自从mysql被oracle收购商业化之后,mysql之父在mysql5.5开源的版本的基础上重新开了一个分支,centos也把MariaDB作为mysql的默认 ...

  6. Spring中通配符(转)

    一.加载路径中的通配符:?(匹配单个字符),*(匹配除/外任意字符).**/(匹配任意多个目录) classpath:app-Beans.xml 说明:无通配符,必须完全匹配   classpath: ...

  7. 使用Intellij中的Spring Initializr来快速构建Spring Boot/Cloud工程

    在之前的所有Spring Boot和Spring Cloud相关博文中,都会涉及Spring Boot工程的创建.而创建的方式多种多样,我们可以通过Maven来手工构建或是通过脚手架等方式快速搭建,也 ...

  8. input框添加阴影效果

    .input:hover,.input:focus{ border:1px solid #85afe1; -webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0 ...

  9. Spring获取HttpServletRequest对象

    <!-- WEB.XML中配置相关的监听机制 -->  <listener>   <listener-class>  org.springframework.web ...

  10. 1517 u Calculate e

    1. 最前面的格式要记得输入. 2. 计算的时候要从3开始重新计算, 否则会丢失精度. 3. 更快的方式就是打表. #include <iostream> using namespace ...