访问通讯录
访问通讯录
技术博客http://www.cnblogs.com/ChenYilong/ " 新浪微博http://weibo.com/luohanchenyilong "

通讯录简介
? iOS提供了AddressBook.framework框架,允许开发者与设备中的通 讯录进行数据交互

技术博客http://www.cnblogs.com/ChenYilong/ " 新浪微博http://weibo.com/luohanchenyilong "


通讯录简介
? iOS提供了AddressBook.framework框架,允许开发者与设备中的通 讯录进行数据交互


通讯录授权
? 背景
?? 自从 iOS6 以来,苹果严格限制了如何访问用户个人信息,比如通讯录信息
?? 当尝试访问用户个人信息时,会弹出一个对话框询问用户是否允许程序对个 人数据进行访问,比如通讯录
? 结论
?? 要想访问用户的通讯录,这是需要用户授权的
?? 为了保证正常访问用户的通讯录,需要检查一下是否可以进行访问,也就是 程序的授权状态


查询授权状态
? 可以调用ABAddressBookGetAuthorizationStatus函数进行查询授权状态,返回值有以下 几种情况:
?? kABAuthorizationStatusNotDetermined = 0 用户还没有决定是否授权你的程序进行访问
?? kABAuthorizationStatusRestricted = 1 iOS设备上的家长控制或其它一些许可配置阻止了你的程序与通讯录数据库进行交互
?? kABAuthorizationStatusDenied
= 2 用户明确的拒绝了你的程序对通讯录的访问
?? kABAuthorizationStatusAuthorized
= 3 用户已经授权给你的程序对通讯录进行访问
// 获得授权状态 ABAuthorizationStatus status =ABAddressBookGetAuthorizationStatus();

申请授权
? 如果应用的授权状态是kABAuthorizationStatusNotDetermined,那么可以使 用ABAddressBookRequestAccessWithCompletion函数请求用户授权对通讯录 的访问
? ABAddressBookRequestAccessWithCompletion函数的第1个参数是通讯录实 例、第2个参数是一个block,无论授权结果如何,都会调用,并传入一个bool变量表示授权成功还是失败
? 一般都是在程序启动完毕后就申请授权(在AppDelegate的application:didFinishLaunchingWithOptions:方法中)

获得所有的联系人数据
? 授权成功后,可以通过调用ABAddressBookCopyArrayOfAllPeople获得所有的 联系人数据
? 这个函数返回一个CFArrayRef类型的数组// 获得所有的联系人 CFArrayRef array =ABAddressBookCopyArrayOfAllPeople(book);// 联系人的总数 int count =CFArrayGetCount(array);
for (int i = 0; i < count; i++){
// 获得某个联系人 ABRecordRef person =CFArrayGetValueAtIndex(array, i);
}
// 释放 CFRelease(array);
? 通讯录数组中的每条记录都是一个ABRecordRef类型的数据,可以是一个群或一 个人

获得所有的联系人数据
? 为了方便操作,也可以将CFArrayRef转成NSArray类型的数组 NSArray *array = (__bridge NSArray*)
ABAddressBookCopyArrayOfAllPeople(book);int count = array.count;
for (int i = 0; i < count; i++){
ABRecordRef person = (__bridgeABRecordRef)array[i]; }

获得联系人的简单属性
? 一个联系人就是一个ABRecordRef,每个联系人都有自己的属性,比如名字、 电话、邮件等
? 使用ABRecordCopyValue函数可以从ABRecordRef中获得联系人的属性
? ABRecordCopyValue函数接收2个参数,第1个参数是ABRecordRef实例,第
2个参数决定想要获得哪个属性 // 获得名
CFStringRef firstName =ABRecordCopyValue(person,kABPersonFirstNameProperty);
// 获得姓 CFStringRef lastName =ABRecordCopyValue(person,
kABPersonLastNameProperty);
? kABPersonFirstNameProperty和kABPersonLastNameProperty属性 返回的都是CFStringRef类型的数据,由于是Copy出来的,最后需要 CFRelease一下
? 所有的属性常量值都定义在了ABPerson.h头文件中

获得联系人的简单属性
? 为了方便操作,也可以将CFStringRef转为 NSString进行操作 // 获得名
NSString *firstName = (__bridge NSString*) ABRecordCopyValue(person,kABPersonFirstNameProperty);
// 获得姓
NSString *lastName = (__bridge NSString *)ABRecordCopyValue(person,kABPersonLastNameProperty);

获得联系人的复杂属性
? 前面获得了联系人的姓、名属性值,都是非常简单的,一个属性对应一个字符串 值
? 联系人的有些属性值就没这么简单,一个属性可能会包含多个值
?? 比如邮箱,分为工作邮箱、住宅邮箱、其他邮箱等
?? 比如电话,分为工作电话、住宅电话、其他电话等
? 如果是复杂属性,那么ABRecordCopyValue函数返回的就是ABMultiValueRef 类型的数据
? 比如获取邮件数据ABMultiValueRefemails = ABRecordCopyValue(person,
kABPersonEmailProperty); // .......CFRelease(emails);

获得联系人的复杂属性
? 获得所有的邮箱地址int count =ABMultiValueGetCount(emails); for (int i = 0; i < count; i++){
// 获得标签名 "CFStringRef emailLabel =ABMultiValueCopyLabelAtIndex(emails, i);
// 转为本地标签名(能看得懂的标签名,比如work、home) "CFStringRef localizedEmailLabel =
ABAddressBookCopyLocalizedLabel(emailLabel);
// 获得邮件地址值 "CFStringRef email =ABMultiValueCopyValueAtIndex(emails, i);
NSLog(@"%@-%@:%@", emailLabel, localizedEmailLabel, email);
// 释放
CFRelease(emailLabel);CFRelease(localizedEmailLabel);CFRelease(email);
}

获得联系人的复杂属性
? 如果不想管理内存,可以将CFStringRef转为NSString // 获得标签名
NSString *emailLabel = (__bridge NSString*) (ABMultiValueCopyLabelAtIndex(emails, i));
// 转为本地标签名(能看得懂的标签名,比如work、home)
NSString *localizedEmailLabel = (__bridgeNSString *) (ABAddressBookCopyLocalizedLabel((__bridgeCFStringRef) (emailLabel)));
// 获得邮件地址值 NSString *email = (__bridge NSString *)
(ABMultiValueCopyValueAtIndex(emails, i));
NSLog(@"%@-%@:%@", emailLabel, localizedEmailLabel, email);

添加联系人的步骤
? 添加联系人的步骤
?? 通过ABPersonCreate函数创建一个新的联系人(返回ABRecordRef)
?? 通过ABRecordSetValue函数设置联系人的属性
?? 通过ABAddressBookAddRecord函数将联系人添加到通讯录数据库中
?? 通过ABAddressBookSave函数保存刚才所作的修改
? 可以通过ABAddressBookHasUnsavedChanges函数判断是否有未保存的 修改
? 当决定是否更改通讯录数据库后,你可以分别使用 AbAddressBookSave 或ABAddressBookRevert 方式来保存或放弃更改

添加联系人代码实现
// 创建联系人 ABRecordRef person =ABPersonCreate();
// 设置属性 ABRecordSetValue(person,kABPersonFirstNameProperty, @"明杰", NULL);ABRecordSetValue(person,kABPersonLastNameProperty, @"李", NULL);
// 通讯录实例 ABAddressBookRef book =ABAddressBookCreateWithOptions(NULL, NULL); // 添加联系人 ABAddressBookAddRecord(book, person,NULL);
// 保存修改 ABAddressBookSave(book, NULL);
// 释放 CFRelease(person);
CFRelease(book);

添加一些复杂的属性
? 前面添加了姓、名两个简单的属性,下面添加一个复杂属性,比如邮箱 // 设置邮箱属性的内容
ABMultiValueRef email =ABMultiValueCreateMutable(kABStringPropertyType);
// 工作邮箱ABMultiValueAddValueAndLabel(email,@"wok@qq.com",
kABWorkLabel, NULL); // 家庭邮箱
ABMultiValueAddValueAndLabel(email,@"home@qq.com", kABHomeLabel, NULL);
// 添加邮箱属性 ABRecordSetValue(person,kABPersonEmailProperty, email,
NULL); CFRelease(email);

添加群组的步骤
? 添加群组的步骤大体和添加联系人一致?? 通过ABPersonCreate函数创建一个新的组(返回ABRecordRef) ?? 通过ABRecordSetValue函数设置组名?? 通过ABAddressBookAddRecord函数将组添加到通讯录数据库中 ?? 通过ABAddressBookSave函数保存刚才所作的修改

添加群组代码实现
// 创建组 ABRecordRef group = ABGroupCreate();
// 设置组名 ABRecordSetValue(group,kABGroupNameProperty, @"家人", NULL);
// 通讯录实例 ABAddressBookRef book =ABAddressBookCreateWithOptions(NULL, NULL); // 添加组ABAddressBookAddRecord(book, group, NULL);
// 保存修改 ABAddressBookSave(book, NULL);
CFRelease(book);
CFRelease(group);
? 上面代码添加的是一个空的群组,里面没有任何联系人

其他函数
? 如果想获取所有的群组信息,可以使用ABAddressBookCopyArrayOfAllGroups函数
? 如果想添加联系人到组中,可以使用ABGroupAddMember函数? 如果想从组中移除联系人,可以使用ABGroupRemoveMember函数
? 如果想从通讯录中移除组或者联系人,可以使用ABAddressBookRemoveRecord函数

操作联系人的头像
? 想操作联系人的头像,有以下函数??BPersonHasImageData 判断通讯录中的联系人是否有图片
?? ABPersonCopyImageData 取得图片数据(假如有的话)
?? ABPersonSetImageData 设置联系人的图片数据

设置图片数据
?NSData*data=UIImageJPEGRepresentation([UIImageimageNamed:@"lufy.jpeg"], 1);
? ABPersonSetImageData(person,(__bridgeCFDataRef)(data), NULL);

获得图片数据
if(ABPersonHasImageData(person)) {NSData *data = (__bridge NSData
*)ABPersonCopyImageData(person);
_imageView.image = [UIImageimageWithData:data];
}

// 获得授权状态 ABAuthorizationStatus status =ABAddressBookGetAuthorizationStatus();

申请授权
? 如果应用的授权状态是kABAuthorizationStatusNotDetermined,那么可以使 用ABAddressBookRequestAccessWithCompletion函数请求用户授权对通讯录 的访问
? ABAddressBookRequestAccessWithCompletion函数的第1个参数是通讯录实 例、第2个参数是一个block,无论授权结果如何,都会调用,并传入一个bool变量表示授权成功还是失败
? 一般都是在程序启动完毕后就申请授权(在AppDelegate的application:didFinishLaunchingWithOptions:方法中)

获得所有的联系人数据
? 授权成功后,可以通过调用ABAddressBookCopyArrayOfAllPeople获得所有的 联系人数据
? 这个函数返回一个CFArrayRef类型的数组// 获得所有的联系人 CFArrayRef array =ABAddressBookCopyArrayOfAllPeople(book);// 联系人的总数 int count =CFArrayGetCount(array);
for (int i = 0; i < count; i++){
// 获得某个联系人 ABRecordRef person =CFArrayGetValueAtIndex(array, i);
}
// 释放 CFRelease(array);
? 通讯录数组中的每条记录都是一个ABRecordRef类型的数据,可以是一个群或一 个人

获得所有的联系人数据
? 为了方便操作,也可以将CFArrayRef转成NSArray类型的数组 NSArray *array = (__bridge NSArray*)
ABAddressBookCopyArrayOfAllPeople(book);int count = array.count;
for (int i = 0; i < count; i++){
ABRecordRef person = (__bridgeABRecordRef)array[i]; }

获得联系人的简单属性
? 一个联系人就是一个ABRecordRef,每个联系人都有自己的属性,比如名字、 电话、邮件等
? 使用ABRecordCopyValue函数可以从ABRecordRef中获得联系人的属性
? ABRecordCopyValue函数接收2个参数,第1个参数是ABRecordRef实例,第
2个参数决定想要获得哪个属性 // 获得名
CFStringRef firstName =ABRecordCopyValue(person,kABPersonFirstNameProperty);
// 获得姓 CFStringRef lastName =ABRecordCopyValue(person,
kABPersonLastNameProperty);
? kABPersonFirstNameProperty和kABPersonLastNameProperty属性 返回的都是CFStringRef类型的数据,由于是Copy出来的,最后需要 CFRelease一下
? 所有的属性常量值都定义在了ABPerson.h头文件中

获得联系人的简单属性
? 为了方便操作,也可以将CFStringRef转为 NSString进行操作 // 获得名
NSString *firstName = (__bridge NSString*) ABRecordCopyValue(person,kABPersonFirstNameProperty);
// 获得姓
NSString *lastName = (__bridge NSString *)ABRecordCopyValue(person,kABPersonLastNameProperty);

获得联系人的复杂属性
? 前面获得了联系人的姓、名属性值,都是非常简单的,一个属性对应一个字符串 值
? 联系人的有些属性值就没这么简单,一个属性可能会包含多个值
?? 比如邮箱,分为工作邮箱、住宅邮箱、其他邮箱等
?? 比如电话,分为工作电话、住宅电话、其他电话等
? 如果是复杂属性,那么ABRecordCopyValue函数返回的就是ABMultiValueRef 类型的数据
? 比如获取邮件数据ABMultiValueRefemails = ABRecordCopyValue(person,
kABPersonEmailProperty); // .......CFRelease(emails);

获得联系人的复杂属性
? 获得所有的邮箱地址int count =ABMultiValueGetCount(emails); for (int i = 0; i < count; i++){
// 获得标签名 "CFStringRef emailLabel =ABMultiValueCopyLabelAtIndex(emails, i);
// 转为本地标签名(能看得懂的标签名,比如work、home) "CFStringRef localizedEmailLabel =
ABAddressBookCopyLocalizedLabel(emailLabel);
// 获得邮件地址值 "CFStringRef email =ABMultiValueCopyValueAtIndex(emails, i);
NSLog(@"%@-%@:%@", emailLabel, localizedEmailLabel, email);
// 释放
CFRelease(emailLabel);CFRelease(localizedEmailLabel);CFRelease(email);
}

获得联系人的复杂属性
? 如果不想管理内存,可以将CFStringRef转为NSString // 获得标签名
NSString *emailLabel = (__bridge NSString*) (ABMultiValueCopyLabelAtIndex(emails, i));
// 转为本地标签名(能看得懂的标签名,比如work、home)
NSString *localizedEmailLabel = (__bridgeNSString *) (ABAddressBookCopyLocalizedLabel((__bridgeCFStringRef) (emailLabel)));
// 获得邮件地址值 NSString *email = (__bridge NSString *)
(ABMultiValueCopyValueAtIndex(emails, i));
NSLog(@"%@-%@:%@", emailLabel, localizedEmailLabel, email);

添加联系人的步骤
? 添加联系人的步骤
?? 通过ABPersonCreate函数创建一个新的联系人(返回ABRecordRef)
?? 通过ABRecordSetValue函数设置联系人的属性
?? 通过ABAddressBookAddRecord函数将联系人添加到通讯录数据库中
?? 通过ABAddressBookSave函数保存刚才所作的修改
? 可以通过ABAddressBookHasUnsavedChanges函数判断是否有未保存的 修改
? 当决定是否更改通讯录数据库后,你可以分别使用 AbAddressBookSave 或ABAddressBookRevert 方式来保存或放弃更改

添加联系人代码实现
// 创建联系人 ABRecordRef person =ABPersonCreate();
// 设置属性 ABRecordSetValue(person,kABPersonFirstNameProperty, @"明杰", NULL);ABRecordSetValue(person,kABPersonLastNameProperty, @"李", NULL);
// 通讯录实例 ABAddressBookRef book =ABAddressBookCreateWithOptions(NULL, NULL); // 添加联系人 ABAddressBookAddRecord(book, person,NULL);
// 保存修改 ABAddressBookSave(book, NULL);
// 释放 CFRelease(person);
CFRelease(book);

添加一些复杂的属性
? 前面添加了姓、名两个简单的属性,下面添加一个复杂属性,比如邮箱 // 设置邮箱属性的内容
ABMultiValueRef email =ABMultiValueCreateMutable(kABStringPropertyType);
// 工作邮箱ABMultiValueAddValueAndLabel(email,@"wok@qq.com",
kABWorkLabel, NULL); // 家庭邮箱
ABMultiValueAddValueAndLabel(email,@"home@qq.com", kABHomeLabel, NULL);
// 添加邮箱属性 ABRecordSetValue(person,kABPersonEmailProperty, email,
NULL); CFRelease(email);

添加群组的步骤
? 添加群组的步骤大体和添加联系人一致?? 通过ABPersonCreate函数创建一个新的组(返回ABRecordRef) ?? 通过ABRecordSetValue函数设置组名?? 通过ABAddressBookAddRecord函数将组添加到通讯录数据库中 ?? 通过ABAddressBookSave函数保存刚才所作的修改

添加群组代码实现
// 创建组 ABRecordRef group = ABGroupCreate();
// 设置组名 ABRecordSetValue(group,kABGroupNameProperty, @"家人", NULL);
// 通讯录实例 ABAddressBookRef book =ABAddressBookCreateWithOptions(NULL, NULL); // 添加组ABAddressBookAddRecord(book, group, NULL);
// 保存修改 ABAddressBookSave(book, NULL);
CFRelease(book);
CFRelease(group);
? 上面代码添加的是一个空的群组,里面没有任何联系人

其他函数
? 如果想获取所有的群组信息,可以使用ABAddressBookCopyArrayOfAllGroups函数
? 如果想添加联系人到组中,可以使用ABGroupAddMember函数? 如果想从组中移除联系人,可以使用ABGroupRemoveMember函数
? 如果想从通讯录中移除组或者联系人,可以使用ABAddressBookRemoveRecord函数

操作联系人的头像
? 想操作联系人的头像,有以下函数??BPersonHasImageData 判断通讯录中的联系人是否有图片
?? ABPersonCopyImageData 取得图片数据(假如有的话)
?? ABPersonSetImageData 设置联系人的图片数据

设置图片数据
?NSData*data=UIImageJPEGRepresentation([UIImageimageNamed:@"lufy.jpeg"], 1);
? ABPersonSetImageData(person,(__bridgeCFDataRef)(data), NULL);

获得图片数据
if(ABPersonHasImageData(person)) {NSData *data = (__bridge NSData
*)ABPersonCopyImageData(person);
_imageView.image = [UIImageimageWithData:data];
}
