系统权限

iOS 10 plist配置

描述字符串一定要填写,不然会引发包无效的问题,导致构建版本不显示

<!-- 相册 --> 
<key>NSPhotoLibraryUsageDescription</key> 
<string>App需要您的同意,才能访问相册</string> 
<!-- 相机 --> 
<key>NSCameraUsageDescription</key>
<string>App需要您的同意,才能访问相机</string> 
<!-- 麦克风 -->
<key>NSMicrophoneUsageDescription</key> 
<string>App需要您的同意,才能访问麦克风</string> 
<!-- 位置 --> 
<key>NSLocationUsageDescription</key> 
<string>App需要您的同意,才能访问位置</string> 
<!-- 在使用期间访问位置 --> 
<key>NSLocationWhenInUseUsageDescription</key> 
<string>App需要您的同意,才能在使用期间访问位置</string> 
<!-- 始终访问位置 --> 
<key>NSLocationAlwaysUsageDescription</key> 
<string>App需要您的同意,才能始终访问位置</string> 
<!-- 日历 --> 
<key>NSCalendarsUsageDescription</key> 
<string>App需要您的同意,才能访问日历</string> 
<!-- 提醒事项 --> 
<key>NSRemindersUsageDescription</key> 
<string>App需要您的同意,才能访问提醒事项</string> 
<!-- 运动与健身 --> 
<key>NSMotionUsageDescription</key> 
<string>App需要您的同意,才能访问运动与健身</string> 
<!-- 健康更新 -->
<key>NSHealthUpdateUsageDescription</key> 
<string>App需要您的同意,才能访问健康更新</string> 
<!-- 健康分享 --> 
<key>NSHealthShareUsageDescription</key> 
<string>App需要您的同意,才能访问健康分享</string> 
<!-- 蓝牙 --> 
<key>NSBluetoothPeripheralUsageDescription</key> 
<string>App需要您的同意,才能访问蓝牙</string> 
<!-- 媒体资料库 --> 
<key>NSAppleMusicUsageDescription</key> 
<string>App需要您的同意,才能访问媒体资料库</string>

如果不起作用,可以请求后台权限,类似于这样:

<key>UIBackgroundModes</key>
<array>
<!-- 在这里写上你在后台模式下要使用权限对应的key --> 
<string>location</string>
...
</array>

鉴定权限

鉴定权限是很有必要的,防止用户关闭权限后出现crash

DDYAuthorityMaster.h

//  Use : [DDYAuthorityMaster checkCameraAuthority]

#import <Foundation/Foundation.h>

typedef void (^AuthorizedFinishBlock)();

@interface DDYAuthorityMaster : NSObject

#pragma mark - 摄像头权限
+ (void)cameraAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail;
#pragma mark - 麦克风权限
+ (void)audioAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail;
#pragma mark - 相册权限
+ (void)albumAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail;
#pragma mark - 推送通知权限
+ (void)pushNotificationAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail;
#pragma mark - 推送通知权限
+ (void)locationAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail;
#pragma mark - 通讯录权限
+ (void)AddressBookAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail;

/** 麦克风权限 */
+ (void)audioAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show;
/** 摄像头权限 */
+ (void)cameraAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show;
/** 相册使用权限 */
+ (void)albumAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show;
/** 推送通知权限 */
+ (void)pushNotificationAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show;
/** 通讯录权限 */
+ (void)contactsAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show;
/** 定位权限 */
+ (void)locationAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show;

@end

DDYAuthorityMaster.m

/*
 *  不弹出提示或需要在提示框增加详细描述的,需手动在info.plist加一些字段
 *  NSLocationWhenInUseUsageDescription 位置权限 使用期间 状态
 *  NSLocationAlwaysUsageDescription    位置权限 始终    状态
 *
 */

#import "DDYAuthorityMaster.h"
#import "DDYAppDelegate.h"

#define kAPPName [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]
#define CancelText NSLocalizedString(@"Cancel", nil)
#define OKText NSLocalizedString(@"OK", nil)
#define OpenText NSLocalizedString(@"Open Setting", nil)
#define CancelText NSLocalizedString(@"Cancel", nil)
#define CameraText NSLocalizedString(@"Camera", nil)
#define AudioText NSLocalizedString(@"Microphone", nil)
#define AlbumText NSLocalizedString(@"Album", nil)
#define LocationText NSLocalizedString(@"Location", nil)
#define ContactText NSLocalizedString(@"AddressBook", nil)

@import AVFoundation;
@import CoreLocation;

@import AddressBook;    // 通讯录 iOS 9-
@import Contacts;       // 通讯录 iOS 9+

@import AssetsLibrary;  // 相册 iOS 6-9
@import Photos;         // 相册 iOS 8+

@implementation DDYAuthorityMaster

#pragma mark 私有方法
+ (BOOL)checkAuthority:(AVAuthorizationStatus)status {
    return (status == AVAuthorizationStatusAuthorized) || (status == AVAuthorizationStatusNotDetermined);
}
#pragma mark 弹窗提示无权限
+ (void)showAlertController:(AuthorizedFinishBlock)block device:(NSString *)device {
    UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"没有权限" message:[NSString stringWithFormat:@"请开启‘%@’对 %@ 的使用权限",kAPPName,device] preferredStyle:UIAlertControllerStyleAlert];
    [alertC addAction:[UIAlertAction actionWithTitle:CancelText style:UIAlertActionStyleCancel handler:nil]];
    [alertC addAction:[UIAlertAction actionWithTitle:OKText style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
    }]];
    [((DDYAppDelegate *)[UIApplication sharedApplication].delegate).window.rootViewController presentViewController:alertC animated:YES completion:block];
}
#pragma mark iOS10以下可以跳转系统设置
+ (void)showNotificationAlertController:(AuthorizedFinishBlock)block {
    UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"Push Notification Are Off" message:[NSString stringWithFormat:@"Don't miss out on messages from friends.Go\"Setting->Notifications\"to open"] preferredStyle:UIAlertControllerStyleAlert];
    [alertC addAction:[UIAlertAction actionWithTitle:CancelText style:UIAlertActionStyleCancel handler:nil]];
    [alertC addAction:[UIAlertAction actionWithTitle:OpenText style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
    }]];
    [((DDYAppDelegate *)[UIApplication sharedApplication].delegate).window.rootViewController presentViewController:alertC animated:YES completion:block];
}

#pragma mark 摄像头权限
+ (BOOL)checkCameraAuthority {
    return [self checkAuthority:[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]];
}
+ (void)cameraAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail;{
    if ([self checkCameraAuthority]) {
        if (success) {
            success();
        }
    }else{
        [self showAlertController:fail device:CameraText];
    }
}

#pragma mark 麦克风权限
+ (BOOL)checkAudioAuthority {
    return [self checkAuthority:[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]];
}
+ (void)audioAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail{
    if ([self checkAudioAuthority]) {
        if (success) {
            success();
        }
    }else{
        [self showAlertController:fail device:AudioText];
    }
}

#pragma mark 相册权限
+ (BOOL)checkAlbumAuthority {
    return [ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusAuthorized;
}
+ (void)albumAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail {
    if ([self checkAlbumAuthority]) {
        if (success) {
            success();
        }
    }else{
        [self showAlertController:fail device:AlbumText];
    }
}

#pragma mark 位置权限
+ (BOOL)checkLocationAuthority {
    return [CLLocationManager locationServicesEnabled];
}
+ (void)locationAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail {
    
    if ([self checkLocationAuthority]) {
        if (success) {
            success();
        }
    }else{
        [self showAlertController:fail device:LocationText];
    }
}

#pragma mark 推送通知权限
+ (BOOL)checkPushNotificationAuthority {
    return [[UIApplication sharedApplication] currentUserNotificationSettings].types != UIUserNotificationTypeNone;
}
+ (void)pushNotificationAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail {
    
    if ([self checkPushNotificationAuthority]) {
        if (success) {
            success();
        }
    }else{
        [self showNotificationAlertController:fail];
        
    }
}

#pragma mark 通讯录权限
+ (BOOL)checkAddressBookAuthority {
    return ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized || ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined;
}
+ (void)AddressBookAuthorizedSuccess:(AuthorizedFinishBlock)success fail:(AuthorizedFinishBlock)fail{
    
    if ([self checkAddressBookAuthority]) {
        if (success) {
            success();
        }
    } else {
        [self showAlertController:fail device:ContactText];
    }
}


#pragma mark 默认无权限提示
+ (void)showAlertWithAppName:(NSString *)appName device:(NSString *)device
{
    UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"没有权限" message:[NSString stringWithFormat:@"请开启‘%@’对 %@ 的使用权限",appName,device] preferredStyle:UIAlertControllerStyleAlert];
    [alertC addAction:[UIAlertAction actionWithTitle:CancelText style:UIAlertActionStyleCancel handler:nil]];
    [alertC addAction:[UIAlertAction actionWithTitle:OKText style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
    }]];
    [((DDYAppDelegate *)[UIApplication sharedApplication].delegate).window.rootViewController presentViewController:alertC animated:YES completion:nil];
}

#pragma mark 麦克风权限
+ (void)audioAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show
{
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
    switch (authStatus)
    {
        case AVAuthorizationStatusNotDetermined: // 有没有询问过还否开启麦克风权限(用户未确定过)
        {
            [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
                
                if (granted)
                {
                    if (success)
                    {
                        success();
                    }
                }
                else
                {
                    if (show)
                    {
                        [self showAlertWithAppName:@"测试APP" device:@"麦克风"];
                    }
                    if (fail)
                    {
                        fail();
                    }
                }
            }];
        }
            break;
        case AVAuthorizationStatusRestricted:  // 未授权,且用户无法更新,如家长控制情况下
        case AVAuthorizationStatusDenied:      // 用户拒绝App使用该权限
            if (show)
            {
                [self showAlertWithAppName:@"测试APP" device:@"麦克风"];
            }
            if (fail)
            {
                fail();
            }
            break;
        case AVAuthorizationStatusAuthorized:  // 已授权
            if (success)
            {
                success();
            }
            break;
    }
}

#pragma mark 摄像头权限
+ (void)cameraAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show
{
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    switch (authStatus)
    {
        case AVAuthorizationStatusNotDetermined:
        {
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                
                if (granted)
                {
                    NSLog(@"我点击了授权");
                    if (success)
                    {
                        success();
                    }
                }
                else
                {
                    NSLog(@"我点击了拒绝");
                    if (show)
                    {
                        [self showAlertWithAppName:@"测试APP" device:@"摄像头"];
                    }
                    if (fail)
                    {
                        fail();
                    }
                }
            }];
        }
            break;
        case AVAuthorizationStatusRestricted:
        case AVAuthorizationStatusDenied:
            if (show)
            {
                [self showAlertWithAppName:@"测试APP" device:@"摄像头"];
            }
            if (fail)
            {
                fail();
            }
            break;
        case AVAuthorizationStatusAuthorized:
            if (success)
            {
                success();
            }
            break;
    }
}

#pragma mark 相册权限
+ (void)albumAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show
{
//    ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus]; // 6-9
    PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];    // 8+
    switch (authStatus)
    {
    case AVAuthorizationStatusNotDetermined:
        {
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                if (status == PHAuthorizationStatusAuthorized)
                {
                    if (success)
                    {
                        success();
                    }
                }
                else
                {
                    if (show)
                    {
                        [self showAlertWithAppName:@"测试APP" device:@"相册"];
                    }
                    if (fail)
                    {
                        fail();
                    }
                }  
            }];
        }
        break;
    case AVAuthorizationStatusRestricted:
    case AVAuthorizationStatusDenied:
        if (show)
        {
            [self showAlertWithAppName:@"测试APP" device:@"相册"];
        }
        if (fail)
        {
            fail();
        }
        break;
    case AVAuthorizationStatusAuthorized:
        if (success)
        {
            success();
        }
        break;
    }
}

#pragma mark 推送通知权限
+ (void)pushNotificationAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show
{
    UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings];
    switch (settings.types)
    {
        case UIUserNotificationTypeNone:
        {
            UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil];
            [[UIApplication sharedApplication] registerUserNotificationSettings:setting];
        }
            break;
        case UIUserNotificationTypeBadge:
        case UIUserNotificationTypeSound:
        case UIUserNotificationTypeAlert:
            if (success)
            {
                success();
            }
            break;
            
    }
}

#pragma mark 通讯录权限
+ (void)contactsAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show
{
    ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();
    switch (authStatus)
    {
        case AVAuthorizationStatusNotDetermined:
        {
            ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
            ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
                if (granted)
                {
                    if (success)
                    {
                        success();
                    }
                }
                else
                {
                    if (show)
                    {
                        [self showAlertWithAppName:@"测试APP" device:@"通讯录"];
                    }
                    if (fail)
                    {
                        fail();
                    }
                }
            });
        }
            break;
        case AVAuthorizationStatusRestricted:
        case AVAuthorizationStatusDenied:
            if (show)
            {
                [self showAlertWithAppName:@"测试APP" device:@"通讯录"];
            }
            if (fail)
            {
                fail();
            }
            break;
        case AVAuthorizationStatusAuthorized:
            if (success)
            {
                success();
            }
            break;
    }
}

#pragma mark 定位权限
+ (void)locationAuthSuccess:(AuthorityBlock)success fail:(AuthorityBlock)fail alertShow:(BOOL)show
{
    BOOL isLocation = [CLLocationManager locationServicesEnabled];
    if (isLocation)
    {
        NSLog(@"not turn on the location");
        if (success)
        {
            success();
        }
    }
    else
    {
        CLLocationManager *manager = [[CLLocationManager alloc] init];
        //        [manager requestAlwaysAuthorization];//一直获取定位信息
        [manager requestWhenInUseAuthorization];//使用的时候获取定位信息
//        manager.delegate = self;
    }
    CLAuthorizationStatus CLstatus = [CLLocationManager authorizationStatus];
    switch (CLstatus)
    {
        case kCLAuthorizationStatusAuthorizedAlways:
            NSLog(@"Always Authorized");
            break;
        case kCLAuthorizationStatusAuthorizedWhenInUse:
            NSLog(@"AuthorizedWhenInUse");
            break;
        case kCLAuthorizationStatusDenied:
        {
            NSLog(@"Denied");
            if (show)
            {
                [self showAlertWithAppName:@"测试APP" device:@"定位"];
            }
            if (fail)
            {
                fail();
            }
        }
            break;
        case kCLAuthorizationStatusNotDetermined:
            NSLog(@"not Determined");
            break;
        case kCLAuthorizationStatusRestricted:
            NSLog(@"Restricted");
            break;
        default:
            break;
    }
}

- (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;
    }
    
}

@end

权限判定 + 部分在未询问时主动申请 点个星星祝福你
码农不易点星星 scan code

iOS 定位服务、通讯录、日历、提醒事项、照片、蓝牙共享、麦克风、相机等授权检测
iOS10 隐私权限设置问题

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

推荐阅读更多精彩内容