-
前言
iOS通訊錄框架有AddressBook,AddressBookUI,Contacts,ContactsUI.
iOS9 AddressBook,AddressBookUI不推薦使用了,用Contacts,ContactsUI代替。
如果項目支持到iOS8或以下,還是使用AddressBook,AddressBookUI。本篇只涉及AddressBook框架的4個類。
可以看到AddressBook包含內容如下圖:
屏幕快照 2016-04-07 下午9.54.27.png 授權
首先導入頭文件
#import <AddressBook/AddressBook.h>
請求授權的代碼
//如果用戶沒決定過,請求授權
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
//創建通訊錄
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
//請求授權
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
if (granted) {//請求授權頁面用戶同意授權
//讀取通訊錄人員數量,此處不可使用上面請求授權的通訊錄對象,會崩潰
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
//獲取聯系人數量
CFIndex personCount = ABAddressBookGetPersonCount(addressBook);
dispatch_async(dispatch_get_main_queue(), ^{
//xxx
});
CFRelease(addressBook);
}
CFRelease(addressBookRef);
//如果是已授權狀態
} else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
//創建通訊錄
//讀取通訊錄人員數量
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
CFIndex personCount = ABAddressBookGetPersonCount(addressBookRef);
//xxx
CFRelease(addressBookRef);
} else {
[self showAlertWithTitle:@"提醒" message:@"請在設置中打開通訊錄授權"];
}
授權狀態一共有四個值,可以自己點擊去頭文件看一下。為什么release,CoreFoundation框架內存需要手動管理,遇到create,copy,new,retain都需要release。
-
讀取聯系人信息
代碼:
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
//拿到所有聯系人
CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
//數組數量
CFIndex peopleCount = CFArrayGetCount(peopleArray);
for (int i = 0; i < peopleCount; i++) {
//拿到一個人
ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);
//拿到姓名
//姓
NSString *lastNameValue = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
//名
NSString *firstNameValue = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
//拿到多值電話
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
//多值數量
CFIndex phoneCount = ABMultiValueGetCount(phones);
for (int j = 0; j < phoneCount ; j++) {
//電話標簽本地化(例如是住宅,工作等)
NSString *phoneLabel = (__bridge_transfer NSString *)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(phones, j));
//拿到標簽下對應的電話號碼
NSString *phoneValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, j);
}
CFRelease(phones);
//郵箱多值
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
CFIndex emailCount = ABMultiValueGetCount(emails);
for (int k = 0; k < emailCount; k++) {
NSString *emailLabel = (__bridge_transfer NSString *)ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(emails, k));
NSString *emailValue = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(emails, k);
}
CFRelease(emails);
}
CFRelease(addressBook);
CFRelease(peopleArray);
關于__bridge_transfer,是橋接的關鍵字之一,還有__bridge_retained和__bridge,可以自行搜索橋接如有不明白,關鍵的是轉換對象所有權的問題。
- 新增聯系人
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
for (IABPerson *iPerson in array) {
//創建一個聯系人
ABRecordRef person = ABPersonCreate();
//新增姓名
NSString *Name = iPerson.Name;
//轉換為CFString
CFStringRef lastName = (__bridge_retained CFStringRef)Name;
//設置屬性
ABRecordSetValue(person, kABPersonLastNameProperty, lastName, NULL);
CFRelease(lastName);
//新增電話
ABMultiValueRef phones = ABMultiValueCreateMutable(kABMultiStringPropertyType);
//手機標簽設置值
CFStringRef mobile = (__bridge_retained CFStringRef)iPerson.MobilePhone;
ABMultiValueAddValueAndLabel(phones, mobile, kABPersonPhoneMobileLabel, NULL);
CFRelease(mobile);
//住宅標簽設置值
CFStringRef homeTel = (__bridge_retained CFStringRef)iPerson.HomeTel;
ABMultiValueAddValueAndLabel(phones, homeTel, kABHomeLabel, NULL);
CFRelease(homeTel);
//工作標簽設置值
CFStringRef workTel = (__bridge_retained CFStringRef)iPerson.WorkTel;
ABMultiValueAddValueAndLabel(phones, workTel, kABWorkLabel, NULL);
CFRelease(workTel);
//其他標簽設置值
CFStringRef otherTel = (__bridge_retained CFStringRef)iPerson.OtherTel;
ABMultiValueAddValueAndLabel(phones, otherTel, kABOtherLabel, NULL);
CFRelease(otherTel);
//為聯系人的電話多值 設置值
ABRecordSetValue(person, kABPersonPhoneProperty, phones, NULL);
//新增郵箱
ABMultiValueRef emails = ABMultiValueCreateMutable(kABPersonEmailProperty);
//住宅郵箱設置值
CFStringRef email = (__bridge_retained CFStringRef)iPerson.Email;
ABMultiValueAddValueAndLabel(emails, email, kABHomeLabel, NULL);
CFRelease(email);
//為聯系人添加郵箱多值
ABRecordSetValue(person, kABPersonEmailProperty, emails, NULL);
//給通訊錄添加聯系人
ABAddressBookAddRecord(addressBook, person, NULL);
CFRelease(person);
CFRelease(phones);
CFRelease(emails);
}
//保存通訊錄,一定要保存
ABAddressBookSave(addressBook, NULL);
CFRelease(addressBook);
這里有一點就是,電話下面的標簽,如果你在電話屬性下面找
屏幕快照 2016-04-07 下午10.54.50.png
有住宅,工作,其他,但都是傳真。其實是在通用下面,因為郵箱也用得到這些標簽。
屏幕快照 2016-04-07 下午10.56.56.png