如何訪問(wèn)用戶的通訊錄
在iOS中,有2個(gè)框架可以訪問(wèn)用戶的通訊錄
AddressBookUI.framework
提供了聯(lián)系人列表界面归榕、聯(lián)系人詳情界面班利、添加聯(lián)系人界面等
一般用于選擇聯(lián)系人
AddressBook.framework
純C語(yǔ)言的API,僅僅是獲得聯(lián)系人數(shù)據(jù)
沒(méi)有提供UI界面展示,需要自己搭建聯(lián)系人展示界面
里面的數(shù)據(jù)類型大部分基于Core Foundation框架梯找,使用起來(lái)極其蛋疼
從iOS6開始,需要得到用戶的授權(quán)才能訪問(wèn)通訊錄益涧,因此在使用之前锈锤,需要檢查用戶是否已經(jīng)授權(quán)
獲得通訊錄的授權(quán)狀態(tài):ABAddressBookGetAuthorizationStatus()
授權(quán)狀態(tài)
kABAuthorizationStatusNotDetermined
用戶還沒(méi)有決定是否授權(quán)你的程序進(jìn)行訪問(wèn)
kABAuthorizationStatusRestricted
iOS設(shè)備上的家長(zhǎng)控制或其它一些許可配置阻止程序與通訊錄數(shù)據(jù)庫(kù)進(jìn)行交互
kABAuthorizationStatusDenied
用戶明確的拒絕了你的程序?qū)νㄓ嶄浀脑L問(wèn)
kABAuthorizationStatusAuthorized
用戶已經(jīng)授權(quán)給你的程序?qū)νㄓ嶄涍M(jìn)行訪問(wèn)
申請(qǐng)?jiān)L問(wèn)通訊錄
實(shí)例化通訊錄對(duì)象
ABAddressBookRefaddressBook = ABAddressBookCreateWithOptions(NULL, NULL);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(boolgranted, CFErrorReferror) {
if (granted)
{
NSLog(@"授權(quán)成功!");
} else {
NSLog(@"授權(quán)失敗!");
}
});
CFRelease(addressBook);
提示:申請(qǐng)通訊錄訪問(wèn)授權(quán)的代碼闲询,通常放在AppDelegate中
聯(lián)系人屬性定義
所有的屬性常量值都定義在了ABPerson.h頭文件中
聯(lián)系人屬性包括以下類型:
簡(jiǎn)單屬性:姓久免、名等
多重屬性:電話號(hào)碼、電子郵件等
組合屬性:地址等
注意:使用ABRecordCopyValue可以從一條Person記錄中獲取到對(duì)應(yīng)的記錄扭弧,但是后續(xù)處理則需要根據(jù)記錄的具體類型加以區(qū)分
簡(jiǎn)單屬性
一個(gè)聯(lián)系人就是一個(gè)ABRecordRef阎姥,每個(gè)聯(lián)系人都有自己的屬性,比如名字鸽捻、電話呼巴、郵件等
使用ABRecordCopyValue函數(shù)可以從ABRecordRef中獲得聯(lián)系人的簡(jiǎn)單屬性(例如:一個(gè)字符串)
ABRecordCopyValue函數(shù)接收2個(gè)參數(shù)
第1個(gè)參數(shù)是ABRecordRef實(shí)例
第2個(gè)參數(shù)是屬性關(guān)鍵字,定義在ABPerson.h中
ABPersonCopyLocalizedPropertyName函數(shù)可以根據(jù)指定的關(guān)鍵字獲取對(duì)應(yīng)的標(biāo)簽文本
獲得所有的聯(lián)系人數(shù)據(jù)
獲取所有聯(lián)系人記錄
CFArrayRefarray = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSInteger count = CFArrayGetCount(array);
for (NSInteger i =0; i < count; ++i) {
取出一條記錄
ABRecordRef person =
CFArrayGetValueAtIndex(array, i);
取出個(gè)人記錄中的詳細(xì)信息
名
CFStringRef firstNameLabel =
ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty);
CFStringRef firstName =
ABRecordCopyValue(person, kABPersonFirstNameProperty);
CFStringRef
lastNameLabel = ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty);
姓
CFStringRef lastName = ABRecordCopyValue(person,
kABPersonLastNameProperty);
NSLog(@"%@ %@ - %@ %@", lastNameLabel,
lastName, firstNameLabel, firstName);
}
CoreFoundation 與 Foundation之間的橋接
- 獲取通訊錄引用
ABAddressBookRefaddressBook = ABAddressBookCreateWithOptions(NULL, nil);
- 獲取所有聯(lián)系人記錄
NSArray*array = (__bridge NSArray *)(ABAddressBookCopyArrayOfAllPeople(addressBook));
for (NSInteger i = 0;
i < array.count; i++) {
取出一條記錄
ABRecordRef
person = (__bridge ABRecordRef)(array[i]);
取出個(gè)人記錄中的詳細(xì)信息
NSString *firstNameLabel
= (__bridge NSString*)(ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty));
NSString *firstName = (__bridge NSString*)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastNameLabel
= (__bridge NSString*)(ABPersonCopyLocalizedPropertyName(kABPersonLastNameProperty));
NSString *lastName = (__bridge NSString*)(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSLog(@"%@ %@ - %@ %@", lastNameLabel,
lastName, firstNameLabel, firstName);
}
CFRelease(addressBook);
結(jié)論:轉(zhuǎn)換看起來(lái)很美~~~
多重屬性
聯(lián)系人的有些屬性值就沒(méi)這么簡(jiǎn)單御蒲,一個(gè)屬性可能會(huì)包含多個(gè)值
比如郵箱衣赶,分為工作郵箱、住宅郵箱厚满、其他郵箱等
比如電話府瞄,分為工作電話、住宅電話碘箍、其他電話等
如果是復(fù)雜屬性遵馆,那么ABRecordCopyValue函數(shù)返回的就是ABMultiValueRef類型的數(shù)據(jù),例如郵箱或者電話
取電話號(hào)碼
ABMultiValueRefphones = ABRecordCopyValue(person, kABPersonPhoneProperty);
取記錄數(shù)量
NSInteger phoneCount =ABMultiValueGetCount(phones);
遍歷所有的電話號(hào)碼
for (NSInteger i = 0;
i < phoneCount; i++) {
…
獲取復(fù)雜屬性的方法
電話標(biāo)簽
CFStringRefphoneLabel = ABMultiValueCopyLabelAtIndex(phones, i);
本地化電話標(biāo)簽
CFStringRef
phoneLocalLabel = ABAddressBookCopyLocalizedLabel(phoneLabel);
電話號(hào)碼
CFStringRef phoneNumber
= ABMultiValueCopyValueAtIndex(phones, i);
添加聯(lián)系人的步驟
添加聯(lián)系人的步驟
通過(guò)ABPersonCreate函數(shù)創(chuàng)建一個(gè)新的聯(lián)系人(返回ABRecordRef)
通過(guò)ABRecordSetValue函數(shù)設(shè)置聯(lián)系人的屬性
通過(guò)ABAddressBookAddRecord函數(shù)將聯(lián)系人添加到通訊錄數(shù)據(jù)庫(kù)中
通過(guò)ABAddressBookSave函數(shù)保存剛才所作的修改
可以通過(guò)ABAddressBookHasUnsavedChanges函數(shù)判斷是否有未保存的修改
當(dāng)決定是否更改通訊錄數(shù)據(jù)庫(kù)后,你可以分別使用 AbAddressBookSave 或 ABAddressBookRevert 方式來(lái)保存或放棄更改
添加群組的步驟
添加群組的步驟大體和添加聯(lián)系人一致
通過(guò)ABPersonCreate函數(shù)創(chuàng)建一個(gè)新的組(返回ABRecordRef)
通過(guò)ABRecordSetValue函數(shù)設(shè)置組名
通過(guò)ABAddressBookAddRecord函數(shù)將組添加到通訊錄數(shù)據(jù)庫(kù)中
通過(guò)ABAddressBookSave函數(shù)保存剛才所作的修改
操作聯(lián)系人的頭像
想操作聯(lián)系人的頭像丰榴,有以下函數(shù)
BPersonHasImageData
判斷通訊錄中的聯(lián)系人是否有圖片
ABPersonCopyImageData
取得圖片數(shù)據(jù)(假如有的話)
ABPersonSetImageData
設(shè)置聯(lián)系人的圖片數(shù)據(jù)
*******************筆記**********************
一. 通訊錄獲取
通訊錄應(yīng)用場(chǎng)景
最常見(jiàn)的是一些即時(shí)通訊APP, 關(guān)聯(lián)聯(lián)系人;
- 通訊錄獲取方案
1.AddressBookUI.framework 框架
提供了聯(lián)系人列表界面货邓、聯(lián)系人詳情界面、添加聯(lián)系人界面等
一般用于選擇聯(lián)系人
2.AddressBook.framework 框架
純C語(yǔ)言的API多艇,僅僅是獲得聯(lián)系人數(shù)據(jù)
沒(méi)有提供UI界面展示逻恐,需要自己搭建聯(lián)系人展示界面
里面的數(shù)據(jù)類型大部分基于Core Foundation框架,使用起來(lái)極其蛋疼
3.ContactsUI.framework (iOS9.0最新框架)
方案1/方案2 的替代品
4.第三方框架
RHAddressBook
對(duì)AddressBook.framework框架的封裝
獲取通訊錄-AddressBookUI
實(shí)現(xiàn)步驟
1.創(chuàng)建選擇聯(lián)系人的控制器
2.設(shè)置代理(用來(lái)接收用戶選擇的聯(lián)系人信息)
3.彈出聯(lián)系人控制器
4.實(shí)現(xiàn)代理
5.在對(duì)應(yīng)的代理方法中獲取聯(lián)系人信息
- 具體代碼實(shí)現(xiàn)
1.創(chuàng)建選擇聯(lián)系人的控制器
ABPeoplePickerNavigationController
*ppnc = [[ABPeoplePickerNavigationController alloc] init];
2.設(shè)置代理(用來(lái)接收用戶選擇的聯(lián)系人信息)
ppnc.peoplePickerDelegate
= self;
3.彈出聯(lián)系人控制器
[self presentViewController:ppnc animated:YES completion:nil];
4.實(shí)現(xiàn)代理
- 選中某個(gè)聯(lián)系人時(shí)調(diào)用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController
*)peoplePicker didSelectPerson:(ABRecordRef)person
{
}
- 選中某個(gè)聯(lián)系人某個(gè)屬性時(shí)調(diào)用
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController
*)peoplePicker didSelectPerson:(ABRecordRef)person
property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
}
- 點(diǎn)擊了取消按鈕會(huì)執(zhí)行該方法
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController
*)peoplePicker
{
}
5.在對(duì)應(yīng)的代理方法中獲取聯(lián)系人信息
- 獲取選中聯(lián)系人的姓名(姓l(shuí)astname和名firstname)
CFStringRef
firstname = ABRecordCopyValue(person, kABPersonFirstNameProperty);
CFStringRef
lastname = ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString
*firstName = (__bridge_transfer NSString
*)(firstname);
NSString
*lastName = (__bridge_transfer NSString
*)(lastname);
NSLog(@"%@ %@", firstName, lastName);
- 獲取聯(lián)系人的電話號(hào)碼
ABMultiValueRef
phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex
count = ABMultiValueGetCount(phones);
for (CFIndex i = 0; i < count; i++) {
NSString *phoneLabel = (__bridge_transfer
NSString *)ABMultiValueCopyLabelAtIndex(phones, i);
NSString *phoneValue = (__bridge_transfer
NSString *)ABMultiValueCopyValueAtIndex(phones, i);
NSLog(@"label : %@ value : %@",
phoneLabel, phoneValue);
}
- 釋放不再使用的對(duì)象
CFRelease(phones);
獲取通訊錄-AddressBook
實(shí)現(xiàn)步驟
1.請(qǐng)求授權(quán)
2.判斷授權(quán)狀態(tài), 如果已授權(quán), 則繼續(xù); 未授權(quán), 則提示用戶, 并返回;
3.創(chuàng)建通訊錄對(duì)象
4.從通信錄對(duì)象中, 獲取所有的聯(lián)系人
5.遍歷所有的聯(lián)系人
6.釋放不再使用的對(duì)象
- 代碼實(shí)現(xiàn)
1.請(qǐng)求授權(quán)
1.獲取授權(quán)的狀態(tài)
ABAuthorizationStatus
status = ABAddressBookGetAuthorizationStatus();
2.判斷授權(quán)狀態(tài),如果是未決定狀態(tài),才需要請(qǐng)求
if (status == kABAuthorizationStatusNotDetermined)
{
2.1.創(chuàng)建通信錄對(duì)象
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
2.2.請(qǐng)求授權(quán)
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (granted) {
NSLog(@"授權(quán)成功");
} else {
NSLog(@"授權(quán)失敗");
}
});
}
2.判斷授權(quán)狀態(tài), 如果已授權(quán), 則繼續(xù); 未授權(quán), 則提示用戶, 并返回;
1.獲取授權(quán)的狀態(tài)
ABAuthorizationStatus
status = ABAddressBookGetAuthorizationStatus();
2.如果用戶已經(jīng)授權(quán)
if (status != kABAuthorizationStatusAuthorized)return;
3.創(chuàng)建通訊錄對(duì)象
ABAddressBookRef
addressBook = ABAddressBookCreateWithOptions(NULL,
NULL);
4.從通信錄對(duì)象中, 獲取所有的聯(lián)系人
CFArrayRef
peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);
5.遍歷所有的聯(lián)系人
5.遍歷所有的聯(lián)系人(每一個(gè)聯(lián)系人都是一條記錄)
CFIndex
peopleCount = CFArrayGetCount(peopleArray);
for (CFIndex i = 0; i < peopleCount; i++) {
6.獲取到聯(lián)系人
ABRecordRef person = CFArrayGetValueAtIndex(peopleArray, i);
7.獲取姓名
NSString *lastname = (__bridge_transfer
NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *firstName = (__bridge_transfer
NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSLog(@"%@ %@", lastname,
firstName);
}
6.釋放不再使用的對(duì)象
CFRelease(peopleArray);
CFRelease(addressBook);
獲取通訊錄-第三方框架RHAddressBook
實(shí)現(xiàn)步驟
1.集成框架
2.使用框架獲取所有聯(lián)系人信息
- 具體實(shí)現(xiàn)
1.集成框架
- 將整個(gè)工程拖入項(xiàng)目
- 添加工程依賴
Build
Phases -> Target Dependencies -> +
- 添加鏈接項(xiàng)
Build
Settings -> Other Linker Flags -> -ObjC -all_load
- 導(dǎo)入框架頭文件
import <RHAddressBook/AddressBoook.h>
2.使用框架獲取所有聯(lián)系人信息
請(qǐng)求授權(quán)
- 獲取授權(quán)狀態(tài)
RHAuthorizationStatus
status = [RHAddressBook authorizationStatus];
if (status == RHAuthorizationStatusNotDetermined)
{
2. 創(chuàng)建通訊錄對(duì)象
RHAddressBook *addressBook = [[RHAddressBook alloc] init];
3. 請(qǐng)求授權(quán)
[addressBook requestAuthorizationWithCompletion:^(bool granted, NSError *error) {
if (granted)
{
NSLog(@"授權(quán)成功!");
}
else
{
NSLog(@"授權(quán)失敗");
}
}];
}
獲取聯(lián)系人信息
- 判斷當(dāng)前授權(quán)狀態(tài)
RHAuthorizationStatus
status = [RHAddressBook authorizationStatus];
if (status != RHAuthorizationStatusAuthorized) {
return;
}
- 創(chuàng)建通訊錄對(duì)象
RHAddressBook
*addressBook = [[RHAddressBook alloc] init];
- 獲取所有聯(lián)系人
NSArray
*peoples = addressBook.people;
- 遍歷所有聯(lián)系人
for (RHPerson *person in
peoples)
{
4.1 獲取聯(lián)系人姓名
NSString *firstName = person.firstName;
NSString *lastName = person.lastName;
NSLog(@"%@---%@",
firstName, lastName);
4.2 獲取聯(lián)系人電話
RHMultiStringValue *mv = person.phoneNumbers;
for (int
i = 0; i < mv.count; i ++)
{
4.2.1 獲取電話標(biāo)簽
NSString *label = [mv labelAtIndex:i];
4.2.2 獲取電話號(hào)碼
NSString *phone = [mv valueAtIndex:i];
NSLog(@"%@--%@",
label, phone);
}
}