五、通讯录权限
首先导入框架#import <Contacts/Contacts.h>
,并在info.plist中配置NSContactsUsageDescription
字段。
- 获取当前App授权状态
使用CNContactStore
类的类方法authorizationStatusForEntityType:
获取授权状态,参数传入CNEntityTypeContacts
,授权状态枚举为:
typedef NS_ENUM(NSInteger, CNAuthorizationStatus)
{
CNAuthorizationStatusNotDetermined = 0, // 未决定
CNAuthorizationStatusRestricted, // 受限制
CNAuthorizationStatusDenied, // 拒绝
CNAuthorizationStatusAuthorized // 允许
}
- 当未请求过授权时的操作
当授权状态枚举值为CNAuthorizationStatusNotDetermined
时,可以使用CNContactStore
类的实例对象调用实例方法requestAccessForEntityType:completionHandler:
来请求授权(即展示授权弹框,此时最好长期持有该对象以防止超出作用域后被销毁而导致的弹框一闪而逝
),参数传入CNEntityTypeContacts
,block回调用户选择的授权状态。
上述为iOS9.0后的方法,下面介绍iOS9.0前的方法。
9.0前需要使用#import <AddressBook/AddressBook.h>
框架的内容,使用ABAddressBookGetAuthorizationStatus()
函数获得当前授权状态,该状态为枚举类型
typedef CF_ENUM(CFIndex, ABAuthorizationStatus) {
// 未决定
kABAuthorizationStatusNotDetermined = 0, // deprecated, use CNAuthorizationStatusNotDetermined
// 受限制
kABAuthorizationStatusRestricted, // deprecated, use CNAuthorizationStatusRestricted
// 拒绝
kABAuthorizationStatusDenied, // deprecated, use CNAuthorizationStatusDenied
// 允许
kABAuthorizationStatusAuthorized // deprecated, use CNAuthorizationStatusAuthorized
}
同样在枚举值为kABAuthorizationStatusNotDetermined
时使用函数ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {}
来请求授权,其中第一个参数为ABAddressBookRef
类型是函数ABAddressBookCreate()
返回值,block中回调用户授权BOOL值。
完整逻辑代码为:
- (void)addressbook:(void(^)(BOOL allow))callback
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0
/**
iOS 9后支持该框架, 使用前需导入#import <Contacts/Contacts.h>框架
*/
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusNotDetermined) // 用户未决定
{
CNContactStore *store = [[CNContactStore alloc] init];
/** 请求用户授权使用通讯录前需要确保在info.plist中配置了如下字段, 否则会导致crash
<key>NSContactsUsageDescription</key>
<string>自定义提示信息可不填</string>
*/
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
NSLog(@"[通讯录]授权状态是:%@", granted ? @"允许" : @"不允许");
if (callback) {
dispatch_async(dispatch_get_main_queue(), ^{//用GCD的方式,保证在主线程上更新UI
callback(granted);
});
}
}];
}
else if (status == CNAuthorizationStatusRestricted || status == CNAuthorizationStatusDenied) // 限制或禁止
{
NSLog(@"[通讯录]授权状态是:受限或不允许");
if (callback) {
callback(NO);
}
}
else // 允许
{
NSLog(@"[通讯录]授权状态是:允许");
if (callback) {
callback(YES);
}
}
#else
/**
iOS 9以下使用通讯录时貌似需要添加字段, 需导入对应的#import <AddressBook/AddressBook.h>框架
*/
ABAddressBookRef ref = ABAddressBookCreate();
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status != kABAuthorizationStatusAuthorized) { // 不是允许状态时
// 进行弹框请求用户授权
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"Error: %@", (__bridge NSError *)error);
if (callback) {
callback(NO);
}
} else {
if (callback) {
callback(YES);
}
}
});
});
}else { // 允许
if (callback) {
callback(YES);
}
}
#endif