重點 (二十九) : 通訊錄

如何訪問用戶的通訊錄

在iOS中,有2個框架可以訪問用戶的通訊錄

AddressBookUI.framework

提供了聯系人列表界面、聯系人詳情界面、添加聯系人界面等

一般用于選擇聯系人

AddressBook.framework

純C語言的API,僅僅是獲得聯系人數據

沒有提供UI界面展示,需要自己搭建聯系人展示界面

里面的數據類型大部分基于Core Foundation框架,使用起來極其蛋疼

從iOS6開始,需要得到用戶的授權才能訪問通訊錄,因此在使用之前,需要檢查用戶是否已經授權

獲得通訊錄的授權狀態:ABAddressBookGetAuthorizationStatus()

授權狀態

kABAuthorizationStatusNotDetermined

用戶還沒有決定是否授權你的程序進行訪問

kABAuthorizationStatusRestricted

iOS設備上的家長控制或其它一些許可配置阻止程序與通訊錄數據庫進行交互

kABAuthorizationStatusDenied

用戶明確的拒絕了你的程序對通訊錄的訪問

kABAuthorizationStatusAuthorized

用戶已經授權給你的程序對通訊錄進行訪問

申請訪問通訊錄

實例化通訊錄對象

ABAddressBookRefaddressBook = ABAddressBookCreateWithOptions(NULL, NULL);

ABAddressBookRequestAccessWithCompletion(addressBook, ^(boolgranted, CFErrorReferror) {

if (granted)

{

    NSLog(@"授權成功!");

} else {

    NSLog(@"授權失敗!");

}

});

CFRelease(addressBook);

提示:申請通訊錄訪問授權的代碼,通常放在AppDelegate中

聯系人屬性定義

所有的屬性常量值都定義在了ABPerson.h頭文件中

聯系人屬性包括以下類型:

簡單屬性:姓、名等

多重屬性:電話號碼、電子郵件等

組合屬性:地址等

注意:使用ABRecordCopyValue可以從一條Person記錄中獲取到對應的記錄,但是后續處理則需要根據記錄的具體類型加以區分

簡單屬性

一個聯系人就是一個ABRecordRef,每個聯系人都有自己的屬性,比如名字、電話、郵件等

使用ABRecordCopyValue函數可以從ABRecordRef中獲得聯系人的簡單屬性(例如:一個字符串)

ABRecordCopyValue函數接收2個參數

第1個參數是ABRecordRef實例

第2個參數是屬性關鍵字,定義在ABPerson.h中

ABPersonCopyLocalizedPropertyName函數可以根據指定的關鍵字獲取對應的標簽文本

獲得所有的聯系人數據

獲取所有聯系人記錄

CFArrayRefarray = ABAddressBookCopyArrayOfAllPeople(addressBook);

NSInteger count = CFArrayGetCount(array);

for (NSInteger i =0; i < count; ++i) {

取出一條記錄

ABRecordRef person =

CFArrayGetValueAtIndex(array, i);

取出個人記錄中的詳細信息

名

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之間的橋接

  1. 獲取通訊錄引用

ABAddressBookRefaddressBook = ABAddressBookCreateWithOptions(NULL, nil);

  1. 獲取所有聯系人記錄

NSArray*array = (__bridge NSArray *)(ABAddressBookCopyArrayOfAllPeople(addressBook));

for (NSInteger i = 0;
i < array.count; i++) {

    取出一條記錄

    ABRecordRef

person = (__bridge ABRecordRef)(array[i]);

    取出個人記錄中的詳細信息

    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);

結論:轉換看起來很美~~~

多重屬性

聯系人的有些屬性值就沒這么簡單,一個屬性可能會包含多個值

比如郵箱,分為工作郵箱、住宅郵箱、其他郵箱等

比如電話,分為工作電話、住宅電話、其他電話等

如果是復雜屬性,那么ABRecordCopyValue函數返回的就是ABMultiValueRef類型的數據,例如郵箱或者電話

取電話號碼

ABMultiValueRefphones = ABRecordCopyValue(person, kABPersonPhoneProperty);

取記錄數量

NSInteger phoneCount =ABMultiValueGetCount(phones);

遍歷所有的電話號碼

for (NSInteger i = 0;
i < phoneCount; i++) {

獲取復雜屬性的方法

電話標簽

CFStringRefphoneLabel = ABMultiValueCopyLabelAtIndex(phones, i);

本地化電話標簽

CFStringRef
phoneLocalLabel = ABAddressBookCopyLocalizedLabel(phoneLabel);

電話號碼

CFStringRef phoneNumber
= ABMultiValueCopyValueAtIndex(phones, i);

添加聯系人的步驟

添加聯系人的步驟

通過ABPersonCreate函數創建一個新的聯系人(返回ABRecordRef)

通過ABRecordSetValue函數設置聯系人的屬性

通過ABAddressBookAddRecord函數將聯系人添加到通訊錄數據庫中

通過ABAddressBookSave函數保存剛才所作的修改

可以通過ABAddressBookHasUnsavedChanges函數判斷是否有未保存的修改

當決定是否更改通訊錄數據庫后,你可以分別使用 AbAddressBookSave 或 ABAddressBookRevert 方式來保存或放棄更改

添加群組的步驟

添加群組的步驟大體和添加聯系人一致

通過ABPersonCreate函數創建一個新的組(返回ABRecordRef)

通過ABRecordSetValue函數設置組名

通過ABAddressBookAddRecord函數將組添加到通訊錄數據庫中

通過ABAddressBookSave函數保存剛才所作的修改

操作聯系人的頭像

想操作聯系人的頭像,有以下函數

BPersonHasImageData

判斷通訊錄中的聯系人是否有圖片

ABPersonCopyImageData

取得圖片數據(假如有的話)

ABPersonSetImageData

設置聯系人的圖片數據

*******************筆記**********************


一. 通訊錄獲取

  1. 通訊錄應用場景

  2. 最常見的是一些即時通訊APP, 關聯聯系人;

  1. 通訊錄獲取方案

1.AddressBookUI.framework 框架

提供了聯系人列表界面、聯系人詳情界面、添加聯系人界面等

一般用于選擇聯系人

2.AddressBook.framework 框架

純C語言的API,僅僅是獲得聯系人數據

沒有提供UI界面展示,需要自己搭建聯系人展示界面

里面的數據類型大部分基于Core Foundation框架,使用起來極其蛋疼

3.ContactsUI.framework (iOS9.0最新框架)

方案1/方案2 的替代品

4.第三方框架
RHAddressBook

對AddressBook.framework框架的封裝

  1. 獲取通訊錄-AddressBookUI

  2. 實現步驟

1.創建選擇聯系人的控制器

2.設置代理(用來接收用戶選擇的聯系人信息)

3.彈出聯系人控制器

4.實現代理

5.在對應的代理方法中獲取聯系人信息

  1. 具體代碼實現

1.創建選擇聯系人的控制器

ABPeoplePickerNavigationController
*ppnc = [[ABPeoplePickerNavigationController alloc] init];

2.設置代理(用來接收用戶選擇的聯系人信息)

ppnc.peoplePickerDelegate
= self;

3.彈出聯系人控制器

[self presentViewController:ppnc animated:YES completion:nil];

4.實現代理

  1. 選中某個聯系人時調用
  • (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController
    *)peoplePicker didSelectPerson:(ABRecordRef)person

{

}

  1. 選中某個聯系人某個屬性時調用
  • (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController
    *)peoplePicker didSelectPerson:(ABRecordRef)person
    property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier

{

}

  1. 點擊了取消按鈕會執行該方法
  • (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController
    *)peoplePicker

{

}

5.在對應的代理方法中獲取聯系人信息

  1. 獲取選中聯系人的姓名(姓lastname和名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);

  1. 獲取聯系人的電話號碼

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);

}

  1. 釋放不再使用的對象

CFRelease(phones);

  1. 獲取通訊錄-AddressBook

  2. 實現步驟

1.請求授權

2.判斷授權狀態, 如果已授權, 則繼續; 未授權, 則提示用戶, 并返回;

3.創建通訊錄對象

4.從通信錄對象中, 獲取所有的聯系人

5.遍歷所有的聯系人

6.釋放不再使用的對象

  1. 代碼實現

1.請求授權

1.獲取授權的狀態

ABAuthorizationStatus
status = ABAddressBookGetAuthorizationStatus();

2.判斷授權狀態,如果是未決定狀態,才需要請求

if (status == kABAuthorizationStatusNotDetermined)
{

2.1.創建通信錄對象

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);

2.2.請求授權

ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {

  if (granted) {

        NSLog(@"授權成功");


  } else {

        NSLog(@"授權失敗");


  }

});

}

2.判斷授權狀態, 如果已授權, 則繼續; 未授權, 則提示用戶, 并返回;

1.獲取授權的狀態

ABAuthorizationStatus
status = ABAddressBookGetAuthorizationStatus();

2.如果用戶已經授權

if (status != kABAuthorizationStatusAuthorized)return;

3.創建通訊錄對象

ABAddressBookRef
addressBook = ABAddressBookCreateWithOptions(NULL,
NULL);

4.從通信錄對象中, 獲取所有的聯系人

CFArrayRef
peopleArray = ABAddressBookCopyArrayOfAllPeople(addressBook);

5.遍歷所有的聯系人

5.遍歷所有的聯系人(每一個聯系人都是一條記錄)

CFIndex
peopleCount = CFArrayGetCount(peopleArray);

for (CFIndex i = 0; i < peopleCount; i++) {

6.獲取到聯系人

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.釋放不再使用的對象

CFRelease(peopleArray);

CFRelease(addressBook);

  1. 獲取通訊錄-第三方框架RHAddressBook

  2. 實現步驟

1.集成框架

2.使用框架獲取所有聯系人信息

  1. 具體實現

1.集成框架

  1. 將整個工程拖入項目
  1. 添加工程依賴

Build
Phases -> Target Dependencies -> +

  1. 添加鏈接項

Build
Settings -> Other Linker Flags -> -ObjC -all_load

  1. 導入框架頭文件

import <RHAddressBook/AddressBoook.h>

2.使用框架獲取所有聯系人信息

請求授權

  1. 獲取授權狀態

RHAuthorizationStatus
status = [RHAddressBook authorizationStatus];

if (status == RHAuthorizationStatusNotDetermined)

{

2. 創建通訊錄對象

RHAddressBook *addressBook = [[RHAddressBook alloc] init];

3. 請求授權

[addressBook requestAuthorizationWithCompletion:^(bool granted, NSError *error) {

  if (granted)


  {

        NSLog(@"授權成功!");


  }


  else


  {

        NSLog(@"授權失敗");


  }

}];

}

獲取聯系人信息

  1. 判斷當前授權狀態

RHAuthorizationStatus
status = [RHAddressBook authorizationStatus];

if (status != RHAuthorizationStatusAuthorized) {

return;

}

  1. 創建通訊錄對象

RHAddressBook
*addressBook = [[RHAddressBook alloc] init];

  1. 獲取所有聯系人

NSArray
*peoples = addressBook.people;

  1. 遍歷所有聯系人

for (RHPerson *person in
peoples)

{

4.1 獲取聯系人姓名

NSString *firstName = person.firstName;

NSString *lastName = person.lastName;

NSLog(@"%@---%@",
firstName, lastName);

4.2 獲取聯系人電話

RHMultiStringValue *mv = person.phoneNumbers;

for (int
i = 0; i < mv.count; i ++)

{

    4.2.1 獲取電話標簽


  NSString *label = [mv labelAtIndex:i];


 

    4.2.2 獲取電話號碼


  NSString *phone = [mv valueAtIndex:i];


  NSLog(@"%@--%@",

label, phone);

}

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 在ios中,有兩個框架可以訪問用戶的通訊錄 AddressBookUI.framework提供了聯系人列表界面, ...
    Manba_小洛閱讀 991評論 4 12
  • 內容概述 iOS給我們提供了四個框架來供我們使用:iOS9之前,有AddressBookUI.framewor...
    leesum閱讀 1,214評論 0 3
  • 在開發一些應用中,我們如果需要iPhone設備中的通訊錄信息。或者,需要開發通訊錄相關的一些功能。那么就需要了解一...
    鄉村小子閱讀 1,196評論 0 1
  • 獲取通訊錄大體分兩大種、四小種,兩大種分別是基于address框架和contacts框架開發的,四小種就是這兩大種...
    NSlog先生閱讀 938評論 0 0
  • 文/馬吉祥 我愿為水,在明亮里折射璀璨 在時光的浪里獨守一份初心 我愿為水 坦坦蕩蕩,靜靜謐謐 我愿把生命用最美的...
    馬吉祥閱讀 389評論 0 1