做通訊錄授權彈窗的時候,做了很多查詢,所以想做一個防止自己過後忘記的總結,針對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;
}