重点 (二十九) : 通讯录

如何访问用户的通讯录

在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

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

}

}

你可能感兴趣的:(重点 (二十九) : 通讯录)