开发中隐私权限经常使用,自己做了一下总结,并且对其也做了基本的使用.
转换为code是
<key>NSSpeechRecognitionUsageDescription</key>
<string>语音识别</string>
<key>NSSiriUsageDescription</key>
<string>Siri</string>
<key>NSRemindersUsageDescription</key>
<string>提醒事项</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>相册</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>相册</string>
<key>NFCReaderUsageDescription</key>
<string>NFC</string>
<key>kTCCServiceMediaLibrary</key>
<string>音乐</string>
<key>NSMotionUsageDescription</key>
<string>运动与健康</string>
<key>NSMicrophoneUsageDescription</key>
<string>麦克风</string>
<key>NSAppleMusicUsageDescription</key>
<string>媒体资料库</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>定位</string>
<key>NSLocationUsageDescription</key>
<string>定位</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>定位</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>定位</string>
<key>NSHomeKitUsageDescription</key>
<string>HomeKit</string>
<key>NSHealthUpdateUsageDescription</key>
<string>健康更新</string>
<key>NSHealthShareUsageDescription</key>
<string>健康分享</string>
<key>NSFaceIDUsageDescription</key>
<string>Face ID</string>
<key>NSContactsUsageDescription</key>
<string>通讯录</string>
<key>NSCameraUsageDescription</key>
<string>相机</string>
<key>NSCalendarsUsageDescription</key>
<string>日历</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>蓝牙</string>
其中有一些是iOS11增加的.官方文档
1.联网权限
联网权限基本最先出现
导入#import <CoreTelephony/CTCellularData.h> //网络权限
说明:只能获取首次进入APP是否允许蜂窝网络权限,其实也可以不判断
- (void)getNetworkPermissions:(void (^)(BOOL))completion {
CTCellularData *cellularData = [[CTCellularData alloc] init];
CTCellularDataRestrictedState authState = cellularData.restrictedState;
if (authState == kCTCellularDataRestrictedStateUnknown) {
cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state){
if (state == kCTCellularDataNotRestricted) {
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion(YES);
}
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
[self createAlertWithMessage:@"无线数据"];
if (completion) {
completion(NO);
}
});
}
};
} else if (authState == kCTCellularDataNotRestricted){
if (completion) {
completion(YES);
}
} else {
[self createAlertWithMessage:@"无线数据"];
if (completion) {
completion(NO);
}
}
}
2.相册权限
相册权限无非就是获取图片获取图片则分为单张或多张.
权限的获取:导入#import <Photos/Photos.h> //iOS8后
- (void)getPhotoPermissions:(void (^)(BOOL))completion {
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
//首次安装APP,用户还未授权 系统会请求用户授权
if (status == PHAuthorizationStatusNotDetermined) {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
if (status == PHAuthorizationStatusAuthorized) {
if (completion) {
completion(YES);
}
} else {
//点击不允许 给用户提示框
[self createAlertWithMessage:@"相册"];
if (completion) {
completion(NO);
}
}
});
}];
} else if (status == PHAuthorizationStatusAuthorized) {
NSLog(@"%@",[NSThread currentThread]);
if (completion) {
completion(YES);
}
} else {
[self createAlertWithMessage:@"相册"];
if (completion) {
completion(NO);
}
}
}
简单使用:若是单张可用系统的UIImagePickerController iOS 11后则不需要权限就可以,当然我们也可以控制在使用前套上一层权限.具体使用可见demo
多张图片可以用第三方库TZImagePickerController
3.相机权限
相机可用来拍照,扫描二维码,视频等
权限获取:
- (void)getCameraPermissions:(void (^)(BOOL))completion {
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (status == AVAuthorizationStatusNotDetermined) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
//用户接受
if (completion) {
completion(YES);
}
} else {
//用户拒绝
[self createAlertWithMessage:@"相机"];
if (completion) {
completion(NO);
}
}
});
}];
} else if (status == AVAuthorizationStatusAuthorized) {
if (completion) {
completion(YES);
}
} else {
[self createAlertWithMessage:@"相机"];
if (completion) {
completion(NO);
}
}
}
使用:可用系统自带的UIImagePickerController,我自己也自定义了两种相机一个是简单拍照.一个是二维码扫描详细使用可见demo
拍照后可保存图片到相册.两种方法:
#if 0
//方式1:保存图片到系统相册 注意:在保存之前需要获取相册权限
UIImageWriteToSavedPhotosAlbum( self.cameraArr.firstObject, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
#endif
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//2:保存图片到系统相册
[PHAssetChangeRequest creationRequestForAssetFromImage:self.cameraArr.firstObject];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (!success) return ;
NSLog(@"保存成功");
}];
//第一种方式的回调:
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
if (error) {
NSLog(@"保存失败");
} else {
NSLog(@"保存成功");
}
}
4.通讯录权限
通讯录获取联系人和手机号
权限获取:导入#import <Contacts/Contacts.h> //通讯录权限
- (void)getAddressBookPermissions:(void (^)(BOOL))completion {
CNContactStore * contactStore = [[CNContactStore alloc]init];
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] ;
if (status== CNAuthorizationStatusNotDetermined) {
[contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
if (completion) {
completion(NO);
}
return;
}
if (granted) {
if (completion) {
completion(YES);
}
} else {
if (completion) {
completion(NO);
}
[self createAlertWithMessage:@"通讯录"];
}
});
}];
} else if (status== CNAuthorizationStatusAuthorized){
if (completion) {
completion(YES);
}
} else {
if (completion) {
completion(NO);
}
[self createAlertWithMessage:@"通讯录"];
}
}
需要注意的是这是iOS9之后的
使用:用到了自带的CNContactPickerViewController可见demo
5.定位权限
定位权限用来获取地理位置,分为使用期间获取和一直获取
获取权限:#import <CoreLocation/CoreLocation.h> //定位权限
- (void)getAlwaysLocationPermissions:(BOOL)always completion:(void (^)(BOOL))completion {
//先判断定位服务是否可用
if (![CLLocationManager locationServicesEnabled]) {
NSAssert([CLLocationManager locationServicesEnabled], @"Location service enabled failed");
return;
}
BOOL locationEnable = [CLLocationManager locationServicesEnabled];
if (!self.locationManager) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
}
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
dispatch_async(dispatch_get_main_queue(), ^{
if (!locationEnable || (status < 3 && status > 0)) {
if (completion) {
completion(NO);
}
[self createAlertWithMessage:@"位置"];
} else if (status == kCLAuthorizationStatusNotDetermined){
//获取授权认证
self.getLocation = completion;
if (always) {
[_locationManager requestAlwaysAuthorization];
} else {
[_locationManager requestWhenInUseAuthorization]; //使用时开启定位
}
} else {
if (always) {
if (status == kCLAuthorizationStatusAuthorizedAlways) {
if (completion) {
completion(YES);
}
} else {
if (completion) {
completion(NO);
}
}
} else {
if (completion) {
completion(YES);
}
}
}
});
}
完整代码可见demo
使用:可以获取经纬度以及地理位置和对地图的使用,地图的使用用了系统的MapKit具体使用可以看demo
6.蓝牙权限
权限的获取:#import <CoreBluetooth/CoreBluetooth.h> //蓝牙权限
- (void)getBluetoothPermissions:(void(^)(BOOL authorized))completion {
CBPeripheralManagerAuthorizationStatus authStatus = [CBPeripheralManager authorizationStatus];
if (authStatus == CBPeripheralManagerAuthorizationStatusNotDetermined) {
CBCentralManager *cbManager = [[CBCentralManager alloc] init];
[cbManager scanForPeripheralsWithServices:nil options:nil];
} else if (authStatus == CBPeripheralManagerAuthorizationStatusAuthorized) {
if (completion) {
completion(YES);
}
} else {
completion(NO);
}
}
具体的使用自己没有用例.可以参考第三方:BabyBluetooth和EasyBluetooth
7.麦克风权限
麦克风无非就是录音
权限获取:
- (void)getMicrophonePermissions:(void(^)(BOOL authorized))completion {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
if (authStatus == AVAuthorizationStatusNotDetermined) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
if (completion) {
completion(YES);
}
} else {
[self createAlertWithMessage:@"麦克风"];
if (completion) {
completion(NO);
}
}
});
}];
} else if(authStatus == AVAuthorizationStatusAuthorized){
if (completion) {
completion(YES);
}
} else {
[self createAlertWithMessage:@"麦克风"];
if (completion) {
completion(NO);
}
}
}
使用:自己做了一个简单的录音播放的功能具体可见demo
8.推送权限
推送在iOS10上变化较大
权限获取:导入#import <UserNotifications/UserNotifications.h> //推送权限
/** 推送iOS10以上 */
- (void)getPushPermissions:(void(^)(BOOL authorized))completion {
[[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionCarPlay completionHandler:^(BOOL granted, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
if (completion) {
completion(YES);
}
} else {
if (completion) {
completion(NO);
}
[self createAlertWithMessage:@"通知"];
}
});
}];
}
使用可见demo
参考第三方PushNotificationManager
9.语音识别权限
语音识别是iOS10推出需要注意
权限获取:导入#import <Speech/Speech.h> //语音识别
- (void)getSpeechRecognitionPermissions:(void(^)(BOOL authorized))completion {
SFSpeechRecognizerAuthorizationStatus authStatus = [SFSpeechRecognizer authorizationStatus];
if (authStatus == SFSpeechRecognizerAuthorizationStatusNotDetermined) {
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) {
if (completion) {
completion(YES);
}
} else {
[self createAlertWithMessage:@"语音识别"];
if (completion) {
completion(NO);
}
}
});
}];
} else if (authStatus == SFSpeechRecognizerAuthorizationStatusAuthorized){
if (completion) {
completion(YES);
}
} else {
[self createAlertWithMessage:@"语音识别"];
if (completion) {
completion(NO);
}
}
}
对于其使用只是简单的本地文件识别成功,对于一个音乐MP3文件识别不是特别好
使用可见demo
9.日历及提醒事项权限
用到的库
#import <EventKit/EventKit.h> //日历备忘录
//EKEntityTypeEvent 日历
//EKEntityTypeReminder 提醒事项
EKEventStore *eventStore = [[EKEventStore alloc] init];
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
if (completion) {
completion(YES);
}
} else {
if (completion) {
completion(NO);
}
[self createAlertWithMessage:@"日历"];
}
});
}];
使用可见demo
需要注意:添加提醒事项需要打开iCloud里面的日历,日历权限和提醒权限必须同时申请.
不然会出现
Error Domain=EKErrorDomain Code=1 "尚未设定日历。" UserInfo={NSLocalizedDescription=尚未设定日历。
此问题可参考:EKErrorDomain Code=1
10. 获取IDFA
IDFA 全称为 Identity for Advertisers ,即广告标识符。
iOS 14 后需要在 Info.plist 中配置" NSUserTrackingUsageDescription " 及描述文案。也就是权限判断的方式改变了,但是获取的方式并没有改变。然后通过代码获取:
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import <AdSupport/AdSupport.h>
- (void)getIDFA {
if (@available(iOS 14, *)) {
[ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
if (status == ATTrackingManagerAuthorizationStatusAuthorized) {
NSString *idfaString = [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString;
NSLog(@"%@", idfaString);
}
}];
} else {
if ([[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]) {
NSString *idfaString = [[ASIdentifierManager sharedManager] advertisingIdentifier].UUIDString;
NSLog(@"%@", idfaString);
}
}
}
另外还有一些其他不太常用的权限暂时没有总结.
iOS 13 新增一个蓝牙权限
Privacy - Bluetooth Always Usage Description 一直使用蓝牙
注意不要将之前的去掉。
iOS14 当 App 要使用 Bonjour 服务时或者访问本地局域网,使用 mDNS 服务等,都需要授权,如果应用中需要使用 LocalNetwork, 开发者需要在 Info.plist 中配置 Privacy - Local Network Usage Description 详细描述使用的为哪种服务以及用途:
查看使用本地网络的第三方SDK:
grep -r SimplePing .
Privacy - Local Network Usage Description : xx会用到本地网络