iOS9以后出了一個新的ContactsUI來代替原來AddressBook用來獲取通訊錄內信息。
這里簡單介紹下常用的獲取通訊錄內所有聯(lián)系人以及選擇某一個手機號方法。
首先需要先在Info里面加隱私聲明:Privacy - Contacts Usage Description

截屏2021-07-19 下午2.19.56.png
然后在調起之前要先獲取是否有權限:
//檢查通訊錄權限
- (BOOL)checkContactsAuthorization {
__block BOOL hasAuthorized = NO;
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if (status == CNAuthorizationStatusNotDetermined) {
dispatch_semaphore_t sem;
sem = dispatch_semaphore_create(0);
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (error) {
hasAuthorized = NO;
}else{
hasAuthorized = granted;
}
dispatch_semaphore_signal(sem);
}];
//獲取通知設置的過程是異步的,這里需要等待
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
}
else if(status == CNAuthorizationStatusAuthorized) {
hasAuthorized = YES;
}
else {
hasAuthorized = NO;
}
return hasAuthorized;
}
這里要注意在CNAuthorizationStatusNotDetermined狀態(tài),也就是用戶未決定是否授權時候,要加一個dispatch_semaphore_signal等待信號量,等用戶決定是否授權點擊以后,才把結果返回。要不就會直接返回NO,即使用戶后面選擇了允許。
獲取通訊錄:
//要獲取的內容的key
NSArray *keysToFetch = @[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
CNContactFetchRequest *fetchRequest = [[CNContactFetchRequest alloc] initWithKeysToFetch:keysToFetch];
CNContactStore *contactStore = [[CNContactStore alloc] init];
[contactStore enumerateContactsWithFetchRequest:fetchRequest error:nil usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
NSArray *phoneNumbers = contact.phoneNumbers;
for (CNLabeledValue *labelValue in phoneNumbers) {
//遍歷一個人名下的多個電話號碼
CNPhoneNumber *phoneNumber = labelValue.value;
NSString *phone = phoneNumber.stringValue;
}
}];
要獲取某一聯(lián)系人下的所有信息:
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact;
這個方法在點擊通訊錄列表里某一個聯(lián)系人時候就會回調,這里可以獲取到所有標簽及信息。
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact {
NSLog(@"name:%@%@",contact.familyName,contact.givenName);
NSLog(@"公司: %@",contact.organizationName);
//獲取通訊錄某個人所有電話并存入數(shù)組中 需要哪個取哪個
NSMutableArray * arrMPhoneNums = [NSMutableArray array];
for (CNLabeledValue * labValue in contact.phoneNumbers) {
NSString * strPhoneNums = [labValue.value stringValue];
NSLog(@"所有電話是: %@",strPhoneNums);
[arrMPhoneNums addObject:strPhoneNums];
}
//所有郵件地址數(shù)組
NSMutableArray * arrMEmails = [NSMutableArray array];
for (CNLabeledValue * labValue in contact.emailAddresses) {
NSLog(@"email : %@",labValue.value);
[arrMEmails addObject:labValue.value];
}
[picker dismissViewControllerAnimated:YES completion:nil];
}
某一選中聯(lián)系人的某一標簽信息:
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty;
這個方法是聯(lián)系人詳情里點擊了某一標簽后能得到點擊的標簽內容,比如聯(lián)系人有多個手機號,點擊其中的一個,就能返回那一個手機號;
此方法和上面方法不能同時實現(xiàn),如果實現(xiàn)了上面的方法在點擊時候就不會進入聯(lián)系人詳情頁 也就不會回調本方法。
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty {
CNPhoneNumber *number=contactProperty.value;
NSString * numStr = [number stringValue];
if (self.selectPhoneNumBlock) {
self.selectPhoneNumBlock([self formatPhoneNumber:numStr]);
}
[picker dismissViewControllerAnimated:YES completion:nil];
}
另外還有多選的回調方法,但是用到地方不多,和單選形式差不多只不過是在數(shù)組里返回的多個數(shù)據(jù):
- (void)contactPicker:(CNContactPickerViewController )picker didSelectContacts:(NSArray<CNContact> *)contacts;
- (void)contactPicker:(CNContactPickerViewController )picker didSelectContactProperties:(NSArray<CNContactProperty> *)contactProperties;
這里附上demo鏈接:
https://github.com/maomaochong001/ContactsTest