iOS10 权限适配总结

从 iOS10 开始,苹果要求所有 APP 都必须在 info.plist 中显示的声明 APP 所用到的手机权限,包括相机、相册、麦克风、定位、网络、后台任务等等,此外,如果 APP 不支持 HTTPS 的话,还需在 info.plist 中开启 HTTP

HTTP 网络

1
2
3
4
5
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

定位

1
2
3
4
5
6
7
8
9
10
11
12
<key>NSLocationUsageDescription</key>
<string>作用:App需要访问你的位置</string>

<key>NSLocationWhenInUseUsageDescription<key>
<string>作用:App在使用期间访问你的位置</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>作用:App想要始终访问你的位置</string>

Privacy - Location Usage Description
Privacy - Location When In Use Usage Description
Privacy - Location Always Usage Description

由于 iOS8.0 之后定位方法的改变,需要在 info.plist 中进行配置;
Privacy - Location When In Use Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据;
Privacy - Location Always Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据;

  • 检查是否有定位权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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;
}
  • 获取定位权限
1
2
3
4
5
CLLocationManager *manager = [[CLLocationManager alloc] init];
// 一直获取定位信息
[manager requestAlwaysAuthorization];
// 使用的时候获取定位信息
[manager requestWhenInUseAuthorization];

相册

1
2
<key>NSPhotoLibraryUsageDescription</key> 
<string>App需要访问相册</string>
  • 检查是否有相册权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#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;
}
  • 获取相册权限
1
2
3
4
5
6
7
8
9
10
11
12
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {

if (status == PHAuthorizationStatusAuthorized) {

NSLog(@"Authorized");

}else{

NSLog(@"Denied or Restricted");

}
}];

相机

1
2
<key>NSCameraUsageDescription</key>
<string>App需要访问相机</string>
  • 检查是否有相机或麦克风权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#import <AVFoundation/AVFoundation.h>

// 相机权限
AVAuthorizationStatus AVstatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

// 麦克风权限
AVAuthorizationStatus AVstatus2 = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];

switch (AVstatus | AVstatus2) {

case AVAuthorizationStatusAuthorized:

NSLog(@"Authorized");//经授权的
break;

case AVAuthorizationStatusDenied:

NSLog(@"Denied");//拒绝的
break;

case AVAuthorizationStatusNotDetermined:

NSLog(@"not Determined");//不可选择的
break;

case AVAuthorizationStatusRestricted:

NSLog(@"Restricted");//限制的
break;

default:
break;
}
  • 获取相机或麦克风权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 相机权限
[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");
}
}];

麦克风

1
2
<key>NSMicrophoneUsageDescription</key>
<string>App需要访问麦克风</string>

日历

1
2
<key>NSCalendarsUsageDescription</key>
<string>App需要访问日历</string>
  • 检查是否有日历或者备忘录权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#import <EventKit/EventKit.h>

/**
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;
}
  • 获取日历或备忘录权限
1
2
3
4
5
6
7
8
9
10
11
12
13
EKEventStore *store = [[EKEventStore alloc] init];

[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {

if (granted) {

NSLog(@"Authorized");

}else{

NSLog(@"Denied or Restricted");
}
}];

提醒事项

1
2
<key>NSRemindersUsageDescription</key>
<string>App需要访问提醒事项</string>

运动与健身

1
2
<key>NSMotionUsageDescription</key>
<string>App需要访问运动与健身</string>

健康更新

1
2
<key>NSHealthUpdateUsageDescription</key>
<string>App需要访问健康更新 </string>

健康分享

1
2
<key>NSHealthShareUsageDescription</key>
<string>App需要访问健康分享</string>

蓝牙

1
2
<key>NSBluetoothPeripheralUsageDescription</key> 
<string>App需要访问蓝牙</string>

语音转文字权限

1
2
<key>Privacy - Speech Recognition Usage Description</key> 
<string>是否允许此App使用语音识别</string>

媒体资料库

1
2
<key>NSAppleMusicUsageDescription</key>
<string>App需要访问媒体资料库</string>

后台模式

1
2
3
4
5
6
<key>UIBackgroundModes</key>`
<array>
//在这里写上你在后台模式下要使用权限对应的key
<string>location</string>
...
</array>

推送通知权限

  • 检查是否有推送通知权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#import <UserNotifications/UserNotifications.h>

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;
}
  • 获取推送通知权限
1
2
3
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil];

[[UIApplication sharedApplication] registerUserNotificationSettings:setting];

通讯录权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#import <AddressBook/AddressBook.h>

#import <Contacts/Contacts.h>

/**
iOS9之前的通讯录框架:

#import <AddressBook/AddressBook.h>

#import <AddressBookUI/AddressBookUI.h>

iOS9之后的通讯录框架:

#import <Contacts/Contacts.h>

#import <ContactsUI/ContactsUI.h>
*/
  • 检查是否有通讯录权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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;

}
  • 获取通讯录权限
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);

ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {

if (granted) {

NSLog(@"Authorized");

CFRelease(addressBook);

}else{

NSLog(@"Denied or Restricted");

}
});
  • iOS9 之后的通讯录框架
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
CNAuthorizationStatus CNstatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];

switch (CNstatus) {

case CNAuthorizationStatusAuthorized:

NSLog(@"Authorized");
break;

case CNAuthorizationStatusDenied:

NSLog(@"Denied");
break;

case CNAuthorizationStatusNotDetermined:

NSLog(@"not Determined");
break;

case CNAuthorizationStatusRestricted:

NSLog(@"Restricted");
break;

default:
break;
}

CNContactStore *contactStore = [[CNContactStore alloc] init];

[contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {

if (granted) {

NSLog(@"Authorized");

}else{

NSLog(@"Denied or Restricted");
}
}];

用户拒绝授权处理方法

用户拒绝授权后,如果访问相应内容可能会出现一些类似没有数据的情况,此时应该给用户提示,引导用户授权。比如跳转到应用设置:

1
2
3
4
5
6
7
NSURL *settingUrl = [NSURL URLWithString:UIApplicationOpenSettingsURLString];

if ([[UIApplication sharedApplication] canOpenURL:settingUrl]) {

[[UIApplication sharedApplication] openURL:settingUrl];

}