如何訪問用戶的通訊錄
在iOS中,有2個框架可以訪問用戶的通訊錄
- AddressBookUI.framework 提供了聯系人列表界面、聯系人詳情界面、添加聯系人界面等一般用於選擇聯系人
- AddressBook.framework 純C語言的API,僅僅是獲得聯系人數據 沒有提供UI界面展示,需要自己搭建聯系人展示界面 里面的數據類型大部分基於Core Foundation框架
從iOS6開始,需要得到用戶的授權才能訪問通訊錄,因此在使用之前,需要檢查用戶是否已經授權
獲得通訊錄的授權狀態:ABAddressBookGetAuthorizationStatus()
授權狀態
- kABAuthorizationStatusNotDetermined 用戶還沒有決定是否授權你的程序進行訪問
- kABAuthorizationStatusRestricted iOS設備上的家長控制或其它一些許可配置阻止程序與通訊錄數據庫進行交互
- kABAuthorizationStatusDenied 用戶明確的拒絕了你的程序對通訊錄的訪問
- kABAuthorizationStatusAuthorized 用戶已經授權給你的程序對通訊錄進行訪問
申請訪問通訊錄
1 // 實例化通訊錄對象 2 ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL); 3 ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { 4 if (granted) { 5 NSLog(@"授權成功!"); 6 } else { 7 NSLog(@"授權失敗!"); 8 } 9 }); 10 CFRelease(addressBook); 11 12 提示:申請通訊錄訪問授權的代碼,通常放在AppDelegate中
聯系人屬性定義
所有的屬性常量值都定義在了ABPerson.h頭文件中
聯系人屬性包括以下類型:
- 簡單屬性:姓、名等
- 多重屬性:電話號碼、電子郵件等
- 組合屬性:地址等
注意:使用ABRecordCopyValue可以從一條Person記錄中獲取到對應的記錄,但是后續處理則需要根據記錄的具體類型加以區分
簡單屬性
一個聯系人就是一個ABRecordRef,每個聯系人都有自己的屬性,比如名字、電話、郵件等
使用ABRecordCopyValue函數可以從ABRecordRef中獲得聯系人的簡單屬性(例如:一個字符串)
ABRecordCopyValue函數接收2個參數
- 第1個參數是ABRecordRef實例
- 第2個參數是屬性關鍵字,定義在ABPerson.h中
ABPersonCopyLocalizedPropertyName函數可以根據指定的關鍵字獲取對應的標簽文本
獲得所有的聯系人數據
1 // 獲取所有聯系人記錄 2 CFArrayRef array = ABAddressBookCopyArrayOfAllPeople(addressBook); 3 NSInteger count = CFArrayGetCount(array); 4 5 for (NSInteger i = 0; i < count; ++i) { 6 // 取出一條記錄 7 ABRecordRef person = CFArrayGetValueAtIndex(array, i); 8 9 // 取出個人記錄中的詳細信息 10 // 名 11 CFStringRef firstNameLabel = ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty); 12 CFStringRef firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty); 13 CFStringRef lastNameLabel = ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty); 14 // 姓 15 CFStringRef lastName = ABRecordCopyValue(person, kABPersonLastNameProperty); 16 17 NSLog(@"%@ %@ - %@ %@", lastNameLabel, lastName, firstNameLabel, firstName); 18 }
CoreFoundation 與 Foundation之間的橋接
1 // 1. 獲取通訊錄引用 2 ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil); 3 // 2. 獲取所有聯系人記錄 4 NSArray *array = (__bridge NSArray *)(ABAddressBookCopyArrayOfAllPeople(addressBook)); 5 for (NSInteger i = 0; i < array.count; i++) { 6 // 取出一條記錄 7 ABRecordRef person = (__bridge ABRecordRef)(array[i]); 8 // 取出個人記錄中的詳細信息 9 NSString *firstNameLabel = (__bridge NSString *)(ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty)); 10 NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty)); 11 NSString *lastNameLabel = (__bridge NSString *)(ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty)); 12 NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty)); 13 NSLog(@"%@ %@ - %@ %@", lastNameLabel, lastName, firstNameLabel, firstName); 14 } 15 CFRelease(addressBook);
注意:當我們使用AddressBook的時候,必須手動管理內存
多重屬性
聯系人的有些屬性值就沒這么簡單,一個屬性可能會包含多個值
- 比如郵箱,分為工作郵箱、住宅郵箱、其他郵箱等
- 比如電話,分為工作電話、住宅電話、其他電話等
如果是復雜屬性,那么ABRecordCopyValue函數返回的就是ABMultiValueRef類型的數據,例如郵箱或者電話
1 // 取電話號碼 2 ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty); 3 // 取記錄數量 4 NSInteger phoneCount = ABMultiValueGetCount(phones); 5 // 遍歷所有的電話號碼 6 for (NSInteger i = 0; i < phoneCount; i++) { 7 }
獲取復雜屬性的方法
1 // 電話標簽 2 CFStringRef phoneLabel = ABMultiValueCopyLabelAtIndex(phones, i); 3 // 本地化電話標簽 4 CFStringRef phoneLocalLabel = ABAddressBookCopyLocalizedLabel(phoneLabel); 5 // 電話號碼 6 CFStringRef phoneNumber = ABMultiValueCopyValueAtIndex(phones, i);
添加聯系人的步驟
添加聯系人的步驟
- 通過ABPersonCreate函數創建一個新的聯系人(返回ABRecordRef)
- 通過ABRecordSetValue函數設置聯系人的屬性
- 通過ABAddressBookAddRecord函數將聯系人添加到通訊錄數據庫中
- 通過ABAddressBookSave函數保存剛才所作的修改
可以通過ABAddressBookHasUnsavedChanges函數判斷是否有未保存的修改
當決定是否更改通訊錄數據庫后,你可以分別使用 AbAddressBookSave 或 ABAddressBookRevert 方式來保存或放棄更改
添加群組的步驟
添加群組的步驟大體和添加聯系人一致
- 通過ABPersonCreate函數創建一個新的組(返回ABRecordRef)
- 通過ABRecordSetValue函數設置組名
- 通過ABAddressBookAddRecord函數將組添加到通訊錄數據庫中
- 通過ABAddressBookSave函數保存剛才所作的修改
操作聯系人的頭像
想操作聯系人的頭像,有以下函數
- BPersonHasImageData 判斷通訊錄中的聯系人是否有圖片
- ABPersonCopyImageData 取得圖片數據(假如有的話)
- ABPersonSetImageData 設置聯系人的圖片數據
如果覺得這種方式太困難,我們可以使用一個面向對象的訪問通訊錄的框架https://github.com/heardrwt/RHAddressBook,使用方式看項目主頁就行,不難