APP启动时权限的判断包括语音,图片,视频,音频等等

.h文件

import <Foundation/Foundation.h>

/** 权限类型 */
typedef NS_ENUM(NSUInteger, YYAuthorizationType) {
YYAuthorizationTypePhotos = 0, // 相册
YYAuthorizationTypeCamera, // 相机
YYAuthorizationTypeMicrophone, // 麦克风
YYAuthorizationTypeCameraAndMicrophone, // 相机和麦克风 (视频)
YYAuthorizationTypeLocation, // 位置
YYAuthorizationTypeNotification, // 通知
};

/** 权限状态 */
typedef NS_ENUM(NSUInteger, YYAuthorizationStatus) {
YYAuthorizationStatusNotDetermined = 0, // 未询问
YYAuthorizationStatusNoPermission, // 无权限
YYAuthorizationStatusHavePermission, // 有权限
};

@interface YYSystemAuthorization : NSObject

/** 检测用户是否有权限访问通知 */
@property (nonatomic, assign) BOOL isCanUseNotification;

  • (YYSystemAuthorization *)sharedSystemAuthorization;

/**
程序进入后台
*/

  • (void)applicationDidEnterBackground:(UIApplication *)application;

/**
检测某种权限的权限状态 (不包含通知, 通知的权限用"isCanUseNotification"判断)

@param authType 权限类型
@return 当前的权限状态
*/

  • (YYAuthorizationStatus)authorizationStatusForAuthType:(YYAuthorizationType)authType;

/**
检测权限并引导去开启

@param authType 权限类型
@param viewController 相关视图控制器
@param completion 点击确定后回调 (havePermission:是否有权限)
*/

  • (void)detectionAuthAndGuideToOpen:(YYAuthorizationType)authType viewController:(UIViewController *)viewController completion:(void (^)(BOOL havePermission))completion;

/**
无权限, 引导去开启 (不进行权限检测)

@param authType 权限类型
@param viewController 相关视图控制器
@param completion 点击确定后回调 (havePermission:是否有权限)
*/

  • (void)guideToOpenAuth:(YYAuthorizationType)authType viewController:(UIViewController *)viewController completion:(void (^)(BOOL havePermission))completion;

.m文件

import "YYSystemAuthorization.h"

import <Photos/Photos.h>

import <AVFoundation/AVFoundation.h>

import <CoreLocation/CoreLocation.h>

@interface YYSystemAuthorization () <CLLocationManagerDelegate>

/** 相关视图控制器 */
@property (nonatomic, weak) UIViewController *viewController;

/** 点击确定后回调 */
@property (nonatomic, copy) void (^completion)(BOOL havePermission);

/** 位置权限管理对象 */
@property (nonatomic, strong) CLLocationManager *locationManager;

@end

@implementation YYSystemAuthorization

  • (YYSystemAuthorization *)sharedSystemAuthorization {
    static dispatch_once_t onceToken;
    static YYSystemAuthorization *instance;
    dispatch_once(&onceToken, ^{
    instance = [[YYSystemAuthorization alloc] init];
    });
    return instance;
    }

/** 程序进入后台 */

  • (void)applicationDidEnterBackground:(UIApplication *)application {
    if (self.completion) {
    self.completion = nil;
    }
    }

pragma mark - 某种权限的权限状态

/** 某种权限的权限状态 */

  • (YYAuthorizationStatus)authorizationStatusForAuthType:(YYAuthorizationType)authType {
    switch (authType) {
    case YYAuthorizationTypePhotos: // 相册
    return [self photosAuthorizationStatus];
    break;
    case YYAuthorizationTypeCamera: // 相机
    return [self cameraAuthorizationStatus];
    break;
    case YYAuthorizationTypeMicrophone: // 麦克风
    return [self microphoneAuthorizationStatus];
    break;
    case YYAuthorizationTypeLocation: // 位置
    return [self locationAuthorizationStatus];
    break;

      default:
          return YYAuthorizationStatusNotDetermined;
          break;
    

    }
    }

pragma mark - 检测权限并引导去开启

/** 检测权限并引导去开启 */

  • (void)detectionAuthAndGuideToOpen:(YYAuthorizationType)authType viewController:(UIViewController *)viewController completion:(void (^)(BOOL havePermission))completion {
    self.viewController = viewController;
    self.completion = completion;
    switch (authType) {
    case YYAuthorizationTypePhotos: // 相册
    [self detectionPhotosAuthAndGuideToOpen];
    break;
    case YYAuthorizationTypeCamera: // 相机
    [self detectionCameraAuthAndGuideToOpen];
    break;
    case YYAuthorizationTypeMicrophone: // 麦克风
    [self detectionMicrophoneAuthAndGuideToOpen];
    break;
    case YYAuthorizationTypeCameraAndMicrophone: // 相机和麦克风
    [self detectionCameraAndMicrophoneAuthAndGuideToOpen];
    break;
    case YYAuthorizationTypeLocation: // 位置
    [self detectionLocationAuthAndGuideToOpen];
    break;
    case YYAuthorizationTypeNotification: // 通知
    [self detectionNotificationAuthAndGuideToOpen];
    break;

      default:
          break;
    

    }
    }

/** 无权限, 引导去开启 (不进行权限检测) */

  • (void)guideToOpenAuth:(YYAuthorizationType)authType viewController:(UIViewController *)viewController completion:(void (^)(BOOL havePermission))completion {
    self.viewController = viewController;
    self.completion = completion;
    [self handleNoPermissionOfType:authType];
    }

pragma mark - 相册

/** 检测相册权限并引导去开启 */

  • (void)detectionPhotosAuthAndGuideToOpen {
    YYAuthorizationStatus authStatus = [self photosAuthorizationStatus];
    if (authStatus == YYAuthorizationStatusNotDetermined) { // 未询问
    // 第一次询问用户是否进行授权
    // 下面的方法只会在未询问过用户的情况下生效,也就是只能第一次询问的时候调用,如果第一次调用时点击了不允许,再次监测状态时调用无效,只能提示用户去设置中打开开关。
    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    if (status == PHAuthorizationStatusAuthorized) {
    self.completion(YES);
    } else {
    self.completion(NO);
    }
    }
    });
    }];
    } else if (authStatus == YYAuthorizationStatusNoPermission) { // 无权限
    [self handleNoPermissionOfType:YYAuthorizationTypePhotos];
    } else { // 有权限
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(YES);
    }
    });
    }
    }

/** 检测用户的相册权限 */

  • (YYAuthorizationStatus)photosAuthorizationStatus {
    PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
    // 用户尚未做出选择
    if (authStatus == PHAuthorizationStatusNotDetermined) { // 未询问
    return YYAuthorizationStatusNotDetermined;
    } else if (authStatus == PHAuthorizationStatusRestricted || authStatus == PHAuthorizationStatusDenied) { // 无权限
    // 此应用程序没有被授权访问的照片数据
    // 用户已经明确否认了这一照片数据的应用程序访问
    return YYAuthorizationStatusNoPermission;
    }
    // 有权限
    return YYAuthorizationStatusHavePermission;
    }

pragma mark - 相机

/** 检测相机权限并引导去开启 */

  • (void)detectionCameraAuthAndGuideToOpen {
    YYAuthorizationStatus authStatus = [self cameraAuthorizationStatus];
    if (authStatus == YYAuthorizationStatusNotDetermined) { // 未询问
    // 第一次询问用户是否进行授权
    // 下面的方法只会在未询问过用户的情况下生效,也就是只能第一次询问的时候调用,如果第一次调用时点击了不允许,再次监测状态时调用无效,只能提示用户去设置中打开开关。
    [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
    if (!granted) {
    [self handleClickUnallowed];
    }
    }];
    } else if (authStatus == YYAuthorizationStatusNoPermission) { // 无权限
    [self handleNoPermissionOfType:YYAuthorizationTypeCamera];
    } else { // 有权限
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(YES);
    }
    });
    }
    }

/** 检测用户的相机权限 */

  • (YYAuthorizationStatus)cameraAuthorizationStatus {
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (authStatus == AVAuthorizationStatusNotDetermined) { // 用户尚未做出选择
    return YYAuthorizationStatusNotDetermined;
    } else if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) { // 无权限
    // 受限制的
    // 不允许
    return YYAuthorizationStatusNoPermission;
    }
    // 有权限
    return YYAuthorizationStatusHavePermission;
    }

pragma mark - 麦克风

/** 检测麦克风权限并引导去开启 */

  • (void)detectionMicrophoneAuthAndGuideToOpen {
    YYAuthorizationStatus authStatus = [self microphoneAuthorizationStatus];
    if (authStatus == YYAuthorizationStatusNotDetermined) { // 未询问
    // 第一次询问用户是否进行授权
    // [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
    //
    // }];
    // iOS8.0
    [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
    if (!granted) {
    [self handleClickUnallowed];
    }
    }];
    } else if (authStatus == YYAuthorizationStatusNoPermission) { // 无权限
    [self handleNoPermissionOfType:YYAuthorizationTypeMicrophone];
    } else { // 有权限
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(YES);
    }
    });
    }
    }

/** 检测用户的麦克风权限 */

  • (YYAuthorizationStatus)microphoneAuthorizationStatus {
    /**
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    if (authStatus == AVAuthorizationStatusNotDetermined) { // 用户尚未做出选择
    return YYAuthorizationStatusNotDetermined;
    } else if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) { // 无权限
    // 受限制的
    // 不允许
    return YYAuthorizationStatusNoPermission;
    }
    // 有权限
    return YYAuthorizationStatusHavePermission;
    */

    // iOS8.0
    AVAudioSessionRecordPermission recordPermission = [[AVAudioSession sharedInstance] recordPermission];
    if (recordPermission == AVAudioSessionRecordPermissionUndetermined) { // 用户尚未做出选择
    return YYAuthorizationStatusNotDetermined;
    } else if (recordPermission == AVAudioSessionRecordPermissionDenied) { // 无权限
    return YYAuthorizationStatusNoPermission;
    } else { // 有权限
    return YYAuthorizationStatusHavePermission;
    }
    }

pragma mark - 相机和麦克风

/** 检测相机和麦克风权限并引导去开启 */

  • (void)detectionCameraAndMicrophoneAuthAndGuideToOpen {
    __block YYAuthorizationStatus cameraStatus = [self cameraAuthorizationStatus];
    __block YYAuthorizationStatus microphoneStatus = [self microphoneAuthorizationStatus];

    // 相机和麦克风都有权限
    if (cameraStatus == YYAuthorizationStatusHavePermission && microphoneStatus == YYAuthorizationStatusHavePermission) {
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(YES);
    }
    });
    return;
    }

    // 相机和麦克风都不是第一次询问授权
    if (cameraStatus != YYAuthorizationStatusNotDetermined && microphoneStatus != YYAuthorizationStatusNotDetermined) {
    if (cameraStatus == YYAuthorizationStatusNoPermission && microphoneStatus == YYAuthorizationStatusNoPermission) { // 相机和麦克风都没有权限
    [self handleNoPermissionOfType:YYAuthorizationTypeCameraAndMicrophone];
    } else if (cameraStatus == YYAuthorizationStatusNoPermission) { // 相机没有权限
    [self handleNoPermissionOfType:YYAuthorizationTypeCamera];
    } else if (microphoneStatus == YYAuthorizationStatusNoPermission) { // 麦克风没有权限
    [self handleNoPermissionOfType:YYAuthorizationTypeMicrophone];
    }
    return;
    }

    // 第一次询问用户是否进行授权
    if (cameraStatus == YYAuthorizationStatusNotDetermined) { // 相机 未询问
    [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
    if (granted) { // 允许
    cameraStatus = YYAuthorizationStatusHavePermission;
    // 相机和麦克风都有权限
    if (microphoneStatus == YYAuthorizationStatusHavePermission) {
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(YES);
    }
    });
    } else if (microphoneStatus == YYAuthorizationStatusNoPermission) {
    // 麦克风没有权限
    [self handleNoPermissionOfType:YYAuthorizationTypeMicrophone];
    }
    } else { // 不允许
    if (microphoneStatus == YYAuthorizationStatusNoPermission) {
    [self handleClickUnallowed];
    }
    }
    }];
    }

    if (microphoneStatus == YYAuthorizationStatusNotDetermined) { // 麦克风 未询问
    [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
    if (granted) { // 允许
    // 相机和麦克风都有权限
    if (cameraStatus == YYAuthorizationStatusHavePermission) {
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(YES);
    }
    });
    } else if (cameraStatus == YYAuthorizationStatusNoPermission) {
    // 相机没有权限
    [self handleNoPermissionOfType:YYAuthorizationTypeCamera];
    }
    } else { // 不允许
    [self handleClickUnallowed];
    }
    }];
    }
    }

pragma mark - 位置

/** 检测位置权限并引导去开启 */

  • (void)detectionLocationAuthAndGuideToOpen {
    YYAuthorizationStatus authStatus = [self locationAuthorizationStatus];
    if (authStatus == YYAuthorizationStatusNotDetermined) { // 未询问
    // 获取定位授权
    [self requestLocationServicesAuthorization];
    } else if (authStatus == YYAuthorizationStatusNoPermission) { // 无权限
    [self handleNoPermissionOfType:YYAuthorizationTypeLocation];
    } else { // 有权限
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(YES);
    }
    });
    }
    }

/** 检测用户的位置权限 */

  • (YYAuthorizationStatus)locationAuthorizationStatus {
    CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus];
    if (authStatus == kCLAuthorizationStatusNotDetermined) { // 用户尚未做出选择
    return YYAuthorizationStatusNotDetermined;
    } else if (authStatus == kCLAuthorizationStatusRestricted || authStatus == kCLAuthorizationStatusDenied) { // 无权限
    // 受限制的
    // 不允许
    return YYAuthorizationStatusNoPermission;
    }
    // 有权限
    return YYAuthorizationStatusHavePermission;
    }

/** 获取定位授权 */

  • (void)requestLocationServicesAuthorization {
    // CLLocationManager的实例对象一定要保持生命周期的存活
    if (!self.locationManager) {
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    }

    // 使用的时候获取定位信息
    [self.locationManager requestWhenInUseAuthorization];
    // 一直获取定位信息
    //[self.locationManager requestAlwaysAuthorization];
    }

pragma mark - CLLocationManagerDelegate

/** 定位授权状态改变 */

  • (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
    //self.locationManager = nil;
    // 有权限
    if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(YES);
    }
    });
    } else {
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(NO);
    }
    });
    }
    }

pragma mark - 通知

/** 检测通知权限并引导去开启 */

  • (void)detectionNotificationAuthAndGuideToOpen {
    // 检测通知权限
    if (![self isCanUseNotification]) {
    // 无权限
    [self handleNoPermissionOfType:YYAuthorizationTypeNotification];
    } else { // 有权限
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(YES);
    }
    });
    }
    }

/** 检测用户是否有权限访问通知 */

  • (BOOL)isCanUseNotification {
    // 推送关闭
    if ([UIApplication sharedApplication].currentUserNotificationSettings.types == UIUserNotificationTypeNone) {
    // 无权限
    return NO;
    }
    return YES;
    }

pragma mark - 第一次询问授权时, 用户点击了"不允许" 处理

  • (void)handleClickUnallowed {
    dispatch_async(dispatch_get_main_queue(), ^{
    [self.viewController dismissViewControllerAnimated:YES completion:nil];
    if (self.completion) {
    self.completion(NO);
    }
    });
    }

pragma mark - 无权限处理

  • (void)handleNoPermissionOfType:(YYAuthorizationType)authType {
    NSString *alertTitle = nil;
    switch (authType) {
    case YYAuthorizationTypePhotos: // 相册
    alertTitle = @"请在iPhone的“设置-隐私-照片”选项中,允许%@访问你的照片。";
    break;
    case YYAuthorizationTypeCamera: // 相机
    alertTitle = @"请在iPhone的“设置-隐私-相机”选项中,允许%@访问你的相机。";
    break;
    case YYAuthorizationTypeMicrophone: // 麦克风
    alertTitle = @"请在iPhone的“设置-隐私-麦克风”选项中,允许%@访问你的麦克风。";
    break;
    case YYAuthorizationTypeCameraAndMicrophone: // 相机和麦克风
    alertTitle = @"请在iPhone的“设置-隐私”选项中,允许%@访问你的相机和麦克风。";
    break;
    case YYAuthorizationTypeLocation: // 位置
    alertTitle = @"无法获取你的位置信息。\n请到手机系统的[设置]->[隐私]->[定位服务]中打开定位服务,并允许%@使用定位服务。";
    break;
    case YYAuthorizationTypeNotification: // 通知
    alertTitle = @"你现在无法收到新消息通知。\n请到系统“设置”-“通知”-“%@”中开启。";

          break;
          
      default:
          break;
    

    }

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:alertTitle, kAppName] message:nil preferredStyle:UIAlertControllerStyleAlert];

    if (authType == YYAuthorizationTypeNotification) {
    [alertController addAction:[UIAlertAction actionWithTitle:@"以后" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    // 回调
    dispatch_async(dispatch_get_main_queue(), ^{
    if (self.completion) {
    self.completion(NO);
    }
    });
    }]];
    }

    [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    dispatch_async(dispatch_get_main_queue(), ^{
    if (authType == YYAuthorizationTypeNotification) {
    // 引导去开启
    [self guideToOpenAuthorization];
    } else {
    [self.viewController dismissViewControllerAnimated:YES completion:nil];
    }

          // 回调
          if (self.completion) {
              self.completion(NO);
          }
      });
    

    }]];
    [self.viewController presentViewController:alertController animated:YES completion:nil];
    }

/** 引导去开启相关权限 */

  • (void)guideToOpenAuthorization {
    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    if ([[UIApplication sharedApplication] canOpenURL:url]) {
    if (@available(iOS 10.0, *)) {
    [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) {

          }];
      } else {
          [[UIApplication sharedApplication] openURL:url];
      }
    

    }
    }

@end

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容