.h文件
import
/** 权限类型 */
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
import
import
@interface YYSystemAuthorization ()
/** 相关视图控制器 */
@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