iOS开发之通讯录 AddressBook
如何访问用户的通讯录
在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,使用方式看项目主页就行,不难