重点 (二十九) : 通讯录

如何访问用户的通讯录

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

}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容

  • 在ios中,有两个框架可以访问用户的通讯录 AddressBookUI.framework提供了联系人列表界面, ...
    Manba_小洛阅读 976评论 4 12
  • 内容概述 iOS给我们提供了四个框架来供我们使用:iOS9之前,有AddressBookUI.framewor...
    leesum阅读 1,177评论 0 3
  • 在开发一些应用中,我们如果需要iPhone设备中的通讯录信息。或者,需要开发通讯录相关的一些功能。那么就需要了解一...
    乡村小子阅读 1,134评论 0 1
  • 获取通讯录大体分两大种、四小种,两大种分别是基于address框架和contacts框架开发的,四小种就是这两大种...
    NSlog先生阅读 904评论 0 0
  • 文/马吉祥 我愿为水,在明亮里折射璀璨 在时光的浪里独守一份初心 我愿为水 坦坦荡荡,静静谧谧 我愿把生命用最美的...
    马吉祥阅读 369评论 0 1