做通讯录授权弹窗的时候,做了很多查询,所以想做一个防止自己过后忘记的总结,针对iOS不同版本进行使用区分(不包含UI部分)。
参考文章:https://www.jianshu.com/p/df0ea100c3da
iOS8及之前采用的是Addressbook,iOS9以后替换为Contact。其实具体字段中的名称是没有大的改动的,使用过程都相同,就是注意使用方法和具体字段名称的区分。
首先授权
在Xcode中打开项目,进入info列表页,添加通讯录授权权限 Privacy - Contacts Usage Description,其中提示文字可以自行编辑。
授权触发
#import <AddressBookUI/AddressBookUI.h> //引入头文件 iOS8
#import <ContactsUI/ContactsUI.h> //引入头文件 iOS9
//获取系统通讯录权限
//iOS8:
- (void)askUserWithSuccess:(void (^)())success failure:(void (^)())failure
{
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error){
if(granted){
dispatch_async(dispatch_get_main_queue(), ^{
success();
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
failure();
});
}
});
}
//iOS9:
- (void)askUserWithSuccess:(void (^)())success failure:(void (^)())failure
{
[[[CNContactStore alloc]init] requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if(granted){
dispatch_async(dispatch_get_main_queue(), ^{
success();
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
failure();
});
}
}];
}
iOS系统通讯录授权,在首次触发时弹出的为系统弹窗,无论用户是否授权,这个系统弹窗仅会弹出一次。所以需要自行根据用户授权状态进行相应处理。
在书写业务逻辑时,进入通讯录相关时,首先需要判断授权状态,然后根据授权状态进行后续处理,可能的情况:
1、第一次进入,还未授权,触发系统授权弹窗
2、用户同意 - > 进入后续通讯录读取等逻辑
3、用户拒绝 -> 可编写警告框进行状态提示等 (如果用户未对系统弹窗做出反应,默认是为拒绝)
在写的时候可以将iOS8及9做一个兼容,封装成一个方法,之后在方法中判断系统版本,进行后续的调用。
授权状态判断
iOS8及之前:https://www.cnblogs.com/yyyyyyyyqs/p/5562777.html ,这篇对iOS8之前的address框架描述详细,字段齐全
查询授权状态 :
ABAddressBookGetAuthorizationStatus | 函数可以查询对通讯录的访问权限 |
kABAuthorizationStatusNotDetermined | 用户还没有决定是否授权你的程序进行访问 |
kABAuthorizationStatusRestricted | iOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互 |
kABAuthorizationStatusDenied | 用户明确的拒绝了你的程序对通讯录的访问 |
kABAuthorizationStatusAuthorized | 用户已经授权给你的程序对通讯录进行访问 |
iOS9:https://www.jianshu.com/p/fadeb914d1ed ,这篇对contact框架解释较为详细,且对通讯录字段描述详细
CNAuthorizationStatusNotDetermined | 用户还没有决定是否授权你的程序进行访问 |
CNAuthorizationStatusRestricted | iOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互 |
CNAuthorizationStatusDenied | 用户明确的拒绝了你的程序对通讯录的访问 |
CNAuthorizationStatusAuthorized | 用户已经授权给你的程序对通讯录进行访问 |
#import <AddressBookUI/AddressBookUI.h> //引入头文件
//自定义状态监测方法,可用switch,此处使用if进行判断了
- (SXAddressBookAuthStatus)getAuthStatus
{
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status == kABAuthorizationStatusNotDetermined) {
//NSLog(@"还没问呢");
return kSXAddressBookAuthStatusNotDetermined;
}else if (status == kABAuthorizationStatusAuthorized){
//NSLog(@"已经授权");
return kSXAddressBookAuthStatusAuthorized;
}else if (status == kABAuthorizationStatusRestricted){
//NSLog(@"iOS设备上一些许可配置阻止程序与通讯录数据库进行交互");
return kSXAddressBookAuthStatusRestricted;
}else{
//NSLog(@"没有授权");
return kSXAddressBookAuthStatusDenied;
}
}
iOS9及之后:(字段同上,不多注释了)
#import <ContactsUI/ContactsUI.h> //插入头文件
//自定义方法
- (SXAddressBookAuthStatus)getAuthStatus
{
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusNotDetermined) {
return kSXAddressBookAuthStatusNotDetermined;
}else if (status == CNAuthorizationStatusAuthorized){
return kSXAddressBookAuthStatusAuthorized;
}else if (status == CNAuthorizationStatusDenied){
return kSXAddressBookAuthStatusDenied;
}else{
return kSXAddressBookAuthStatusRestricted;
}
}
获得授权之后读取通讯录内容,此处仅获取字段进行处理,后续的UI不做描述
通讯录内容字段:
姓名、昵称、公司等类型均为string
邮件,URL地址、地址、电话号码均为数组
iOS9:
- (NSArray *)getPersonInfoArray
{
NSMutableArray *personArray = [NSMutableArray array];
CNContactStore *contactStore = [[CNContactStore alloc] init];
NSArray *keys = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey, CNContactNicknameKey,CNContactOrganizationNameKey, CNContactEmailAddressesKey,CNContactUrlAddressesKey,CNContactPostalAddressesKey];
//此处,需要获取哪些通讯录字段,需列出
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
[contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
SXPersonInfoEntity *personEntity = [SXPersonInfoEntity new];
//name string
NSString *lastname = contact.familyName;
NSString *firstname = contact.givenName;
NSMutableString *fullname = [[NSString stringWithFormat:@"%@%@",lastname,firstname] mutableCopy];
[fullname replaceOccurrencesOfString:@"(null)" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, fullname.length)];
personEntity.name = fullname;
personEntity.nickname = contact.nickname;
personEntity.company = contact.organizationName;
//email array
NSArray *emailArray = contact.emailAddresses;
NSMutableArray *emailAddress = [[NSMutableArray alloc]init];
for (CNLabeledValue *labeledValue in emailArray) {
NSString *emailContent = labeledValue.value;
[emailAddress addObject:emailContent];
}
personEntity.email = emailAddress;
//phone array
NSMutableArray *fullPhoneStr = [[NSMutableArray alloc]init];
for (CNLabeledValue *labeledValue in contact.phoneNumbers) {
CNPhoneNumber *phoneNumer = labeledValue.value;
NSString *phoneValue = phoneNumer.stringValue;
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"+86" withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"-" withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"(" withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@")" withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@" " withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@" " withString:@""];
[fullPhoneStr addObject:phoneValue];
}
personEntity.phone = fullPhoneStr;
//地址 array todo
NSMutableArray *postalAddress = [[NSMutableArray alloc]init];
for (CNLabeledValue *labeledValue in contact.postalAddresses) {
CNPostalAddress *postalAddr = labeledValue.value;
NSString *address = [NSString stringWithFormat:@"%@\n%@\n%@\n%@\n%@",postalAddr.country,postalAddr.city,postalAddr.state,postalAddr.street,postalAddr.postalCode];
[postalAddress addObject:address];
}
personEntity.address = postalAddress;
//url array
NSMutableArray *urlArray = [[NSMutableArray alloc]init];
for (CNLabeledValue *labeledValue in contact.urlAddresses) {
NSString *urlAddr = labeledValue.value;
[urlArray addObject:urlAddr];
}
personEntity.website = urlArray;
[personArray addObject:personEntity];
}];
return personArray;
}
iOS8:注意写法和iOS9是有区分的,字段获取方式不同
- (NSArray *)getPersonInfoArray
{
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex peopleCount = CFArrayGetCount(peopleArray);
NSMutableArray *personArray = [NSMutableArray array];
for (int i = 0; i < peopleCount; i++) {
SXPersonInfoEntity *personEntity = [SXPersonInfoEntity new];
ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);
//名字 string
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSMutableString *fullname = [[NSString stringWithFormat:@"%@%@",lastName,firstName] mutableCopy];
[fullname replaceOccurrencesOfString:@"(null)" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, fullname.length)];
personEntity.name = fullname;
//昵称 string
NSString *nickname = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonNicknameProperty);
personEntity.nickname = nickname;
//电话号码 array
NSMutableArray *phoneArray = [[NSMutableArray alloc]init];
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
for (NSInteger j=0; j<ABMultiValueGetCount(phones); j++) {
NSString *phoneValue = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phones, j));
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"+86" withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"-" withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@"(" withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@")" withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@" " withString:@""];
phoneValue = [phoneValue stringByReplacingOccurrencesOfString:@" " withString:@""];
[phoneArray addObject:phoneValue];
}
personEntity.phone = phoneArray;
//公司 string
NSString *organization = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonOrganizationProperty);
personEntity.company = organization;
//email array
NSMutableArray *emailArray = [[NSMutableArray alloc]init];
ABMultiValueRef emails= ABRecordCopyValue(person, kABPersonEmailProperty);
for (NSInteger j=0; j<ABMultiValueGetCount(emails); j++) {
NSString *email = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(emails, j));
[emailArray addObject:email];
}
personEntity.email = emailArray;
//address/地址 array
NSMutableArray *addressArray = [[NSMutableArray alloc]init];
ABMultiValueRef address = ABRecordCopyValue(person, kABPersonAddressProperty);
for (int j=0; j<ABMultiValueGetCount(address); j++) {
//地址类型
NSString *type = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(address, j));
NSDictionary * tempDic = (__bridge NSDictionary *)(ABMultiValueCopyValueAtIndex(address, j));
//地址字符串,可以按需求格式化
NSString *adress = [NSString stringWithFormat:@"%@\n%@\n%@\n%@\n%@",[tempDic valueForKey:(NSString*)kABPersonAddressCountryKey],[tempDic valueForKey:(NSString*)kABPersonAddressStateKey],[tempDic valueForKey:(NSString*)kABPersonAddressCityKey],[tempDic valueForKey:(NSString*)kABPersonAddressStreetKey],[tempDic valueForKey:(NSString*)kABPersonAddressZIPKey]];
[addressArray addObject:adress];
}
personEntity.address = addressArray;
//url array
NSMutableArray *urlArray = [[NSMutableArray alloc]init];
ABMultiValueRef url = ABRecordCopyValue(person, kABPersonURLProperty);
for (int m = 0; m < ABMultiValueGetCount(url); m++)
{
NSString * urlLabel = (__bridge NSString*)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(url, m));
NSString * urlContent = (__bridge NSString*)ABMultiValueCopyValueAtIndex(url,m);
[urlArray addObject:urlContent];
}
personEntity.website = urlArray;
[personArray addObject:personEntity];
CFRelease(phones);
CFRelease(emails);
CFRelease(url);
CFRelease(address);
}
CFRelease(addressBook);
CFRelease(peopleArray);
return personArray;
}