如何访问用户的通讯录

在iOS中,有2个框架可以访问用户的通讯录

AddressBookUI.framework

提供了联系人列表界面、联系人详情界面、添加联系人界面等
一般用于选择联系人

AddressBook.framework

纯C语言的API,仅仅是获得联系人数据 没有提供UI界面展示,需要自己搭建联系人展示界面 里面的数据类型大部分基于Core Foundation框架,使用起来极其蛋疼

从iOS6开始,需要得到用户的授权才能访问通讯录,因此在使用之前,需要检 查用户是否已经授权

获得通讯录的授权状态: ABAddressBookGetAuthorizationStatus()

授权状态

➢ kABAuthorizationStatusNotDetermined
● 用户还没有决定是否授权你的程序进行访问

➢ kABAuthorizationStatusRestricted
● iOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互

➢ kABAuthorizationStatusDenied
● 用户明确的拒绝了你的程序对通讯录的访问

➢ kABAuthorizationStatusAuthorized
● 用户已经授权给你的程序对通讯录进行访问

申请访问通讯录

// 实例化通讯录对象
ABAddressBookRef addressBook =ABAddressBookCreateWithOptions(NULL, NULL);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool

granted, CFErrorRef error) {
if (granted) {

NSLog(@"授权成功!"); } else {

NSLog(@"授权失败!"); }

});
CFRelease(addressBook);

提示:申请通讯录访问授权的代码,通常放在AppDelegate中

联系人属性定义

● 所有的属性常量值都定义在了ABPerson.h头文件中

● 联系人属性包括以下类型:
● 简单属性:姓、名等
● 多重属性:电话号码、电子邮件等
● 组合属性:地址等

● 注意:使用ABRecordCopyValue可以从一条Person记录中
获取到对应的记录,但是后续处理则需要根据记录的具体
类型加以区分

简单属性

● 一个联系人就是一个ABRecordRef,每个联系人都有自己的属 性,比如名字、电话、邮件等

● 使用ABRecordCopyValue函数可以从ABRecordRef中获得联系人 的简单属性(例如:一个字符串)

● ABRecordCopyValue函数接收2个参数
● 第1个参数是ABRecordRef实例
● 第2个参数是属性关键字,定义在ABPerson.h中

● ABPersonCopyLocalizedPropertyName函数可以根据指定的关键
字获取对应的标签文本

获得所有的联系人数据

// 获取所有联系人记录
CFArrayRef array =ABAddressBookCopyArrayOfAllPeople(addressBook);

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

// 取出一条记录

   ABRecordRef person =CFArrayGetValueAtIndex(array, i);

// 取出个人记录中的详细信息

// 名

CFStringRef firstNameLabel =ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty);

CoreFoundation 与 Foundation之间的桥接

// 1. 获取通讯录引用
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil);
// 2. 获取所有联系人记录
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类型的数据,例如邮箱或者电话

// 取电话号码

ABMultiValueRef phones =ABRecordCopyValue(person,kABPersonPhoneProperty);

// 取记录数量
NSInteger phoneCount =ABMultiValueGetCount(phones);

// 遍历所有的电话号码

获取复杂属性的方法

// 电话标签

CFStringRef phoneLabel =ABMultiValueCopyLabelAtIndex(phones, i);
// 本地化电话标签
CFStringRef phoneLocalLabel =ABAddressBookCopyLocalizedLabel(phoneLabel);

// 电话号码
CFStringRef phoneNumber =ABMultiValueCopyValueAtIndex(phones, i);

 

添加联系人的步骤

● 添加联系人的步骤
1.通过ABPersonCreate函数创建一个新的联系人(返回ABRecordRef)

2.通过ABRecordSetValue函数设置联系人的属性

3.通过ABAddressBookAddRecord函数将联系人添加到通讯录数据 库中

4.通过ABAddressBookSave函数保存刚才所作的修改
● 可以通过ABAddressBookHasUnsavedChanges函数判断是否有未保存

的修改
● 当决定是否更改通讯录数据库后,你可以分别使用AbAddressBookSave或 ABAddressBookRevert 方式来保存或放弃更改

添加群组的步骤

● 添加群组的步骤大体和添加联系人一致
➢ 通过ABPersonCreate函数创建一个新的组(返回ABRecordRef)

➢ 通过ABRecordSetValue函数设置组名

➢ 通过ABAddressBookAddRecord函数将组添加到通讯录数
据库中

➢ 通过ABAddressBookSave函数保存刚才所作的修改

 

操作联系人的头像

● 想操作联系人的头像,有以下函数
 
● BPersonHasImageData
● 判断通讯录中的联系人是否有图片

● ABPersonCopyImageData
● 取得图片数据(假如有的话)

● ABPersonSetImageData

● 设置联系人的图片数据

实例1:使用AddressBookUI框架

//
// HMViewController.m
// 08-通讯录
//
// Created by apple on 14-8-12.
// Copyright (c) 2014年 heima. All rights reserved.
// #import "HMViewController.h"
#import <AddressBookUI/AddressBookUI.h> @interface HMViewController () <ABPeoplePickerNavigationControllerDelegate>
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *phoneLabel; @end @implementation HMViewController - (void)viewDidLoad
{
[super viewDidLoad]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 弹出联系人列表
ABPeoplePickerNavigationController *ppnc = [[ABPeoplePickerNavigationController alloc] init];
ppnc.peoplePickerDelegate = self;
[self presentViewController:ppnc animated:YES completion:nil];
} #pragma mark - ABPeoplePickerNavigationControllerDelegate
/**
* 当选中了某个联系人就会调用
*
* @return NO : 不会继续执行下一个默认操作。 YES : 按照默认的做法
*/
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
// 设置联系人数据
// person中包括了姓名、电话属性
// copy / new / create / retain, 都需要在不使用的时候release
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
self.nameLabel.text = [NSString stringWithFormat:@"姓名:%@ %@", lastName, firstName]; // 获得电话号码
ABMultiValueRef phone = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex phoneCount = ABMultiValueGetCount(phone);
NSMutableString *phoneStr = [NSMutableString string];
[phoneStr appendString:@"电话:"];
for (int i = ; i<phoneCount; i++) {
NSString *label = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(phone, i));
NSString *value = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phone, i));
[phoneStr appendFormat:@"\n%@ : %@", label, value];
}
self.phoneLabel.text = phoneStr; [peoplePicker dismissViewControllerAnimated:YES completion:nil]; CFRelease(phone);
return NO;
} /**
* 当选中了联系人的某个属性时调用
*
* @return NO : 不会继续执行下一个默认操作。 YES : 按照默认的做法
*/
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{ return NO;
} /**
* 点击了取消按钮
*/
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker
{
[peoplePicker dismissViewControllerAnimated:YES completion:nil];
} @end

实例2:  使用:AddressBook框架(要下载)

#import <AddressBook/AddressBook.h>

@implementation HMAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 1.获得通讯录的授权状态
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status == kABAuthorizationStatusNotDetermined) {
// 2.申请授权
ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL);
ABAddressBookRequestAccessWithCompletion(book, ^(bool granted, CFErrorRef error) {
// 授权完毕后调用
if (granted == YES) { // 允许
NSLog(@"---允许");
} else { // 不允许
NSLog(@"---不允许");
} // 释放对象
CFRelease(book);
});
}
// Override point for customization after application launch.
return YES;
}
#import "HMViewController.h"
#import <AddressBook/AddressBook.h>
#import "AddressBook.h" @interface HMViewController () @end @implementation HMViewController - (void)viewDidLoad
{
[super viewDidLoad]; RHAddressBook *book = [[RHAddressBook alloc] init]; // [book addPerson:<#(RHPerson *)#>];
// [book addPerson:<#(RHPerson *)#>];
// [book addPerson:<#(RHPerson *)#>];
// [book save]; NSArray *people = [book people];
for (RHPerson *p in people) {
NSLog(@"%@ %@", p.firstName, p.lastName); RHMultiValue *phones = p.phoneNumbers;
int phoneCount = phones.count;
for (int i = ; i<phoneCount; i++) {
NSString *label1 = [phones labelAtIndex:i];
NSString *label2 = [phones localizedLabelAtIndex:i];
NSString *value = phones.values[i];
NSLog(@"%@ %@ %@", label1, label2, value);
}
} // ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
// if (status != kABAuthorizationStatusAuthorized) return;
//
// // 1.获得通讯录对象
// ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL);
//
// // 2.访问通讯录中的所有联系人
// CFArrayRef peopleArray = ABAddressBookCopyArrayOfAllPeople(book);
// CFIndex count = CFArrayGetCount(peopleArray);
// for (CFIndex i = 0; i<count; i++) {
// // 取出i位置的联系人
// ABRecordRef people = CFArrayGetValueAtIndex(peopleArray, i);
//
// // 获得姓名
// CFStringRef firstName = ABRecordCopyValue(people, kABPersonFirstNameProperty);
// CFStringRef lastName = ABRecordCopyValue(people, kABPersonLastNameProperty);
// CFStringRef org = ABRecordCopyValue(people, kABPersonOrganizationProperty);
//
//
// NSLog(@"%@ %@ %@", firstName, lastName, org);
// // 获得电话
// ABMultiValueRef phone = ABRecordCopyValue(people, kABPersonPhoneProperty);
// CFIndex phoneCount = ABMultiValueGetCount(phone);
// for (CFIndex j = 0; j<phoneCount; j++) {
// CFStringRef phoneValue = ABMultiValueCopyValueAtIndex(phone, j);
// CFStringRef phoneLabel = ABMultiValueCopyLabelAtIndex(phone, j);
//
// NSLog(@"%@ %@", phoneLabel, phoneValue);
//
// CFRelease(phoneLabel);
// CFRelease(phoneValue);
// }
// CFRelease(firstName);
// CFRelease(lastName);
// CFRelease(org);
// }
//
// // 3.不需要通讯录
// CFRelease(peopleArray);
// CFRelease(book);
} @end

IOS 通讯录 (访问,添加,修改)的更多相关文章

  1. IOS开发笔记 IOS如何访问通讯录

    IOS开发笔记  IOS如何访问通讯录 其实我是反对这类的需求,你说你读我的隐私,我肯定不愿意的. 幸好ios6.0 以后给了个权限控制.当打开app的时候你可以选择拒绝. 实现方法: [plain] ...

  2. iOS通讯录相关知识-浅析

    本文来自于:贞娃儿的博客  http://blog.sina.com.cn/zhenwawaer  在开发一些应用中,我们如果需要iPhone设备中的通讯录信息.或者,需要开发通讯录相关的一些功能.那 ...

  3. 使用vscode访问和修改远程计算机文件

    使用vscode访问和修改远程文件,分三步实现:在远程linux机器上安装rmate:在本地windows上安装openssh:在vscode中安装扩展remote vscode. 1. 在远程lin ...

  4. roundcute 添加修改密码插件

    添加修改密码插件 现打开main.inc.php 文件,搜索“$rcmail_config['plugins']”,找到: // List of active plugins (in plugins/ ...

  5. ASP.NET MVC用存储过程批量添加修改数据

    用Entity Framework 进行数据库交互,在代码里直接用lamda表达式和linq对数据库操作,中间为程序员省去了数据库访问的代码时间,程序员直接可以专注业务逻辑层的编写.但是对于比较复杂的 ...

  6. 向IOS模拟机上添加图片

    [问题] 折腾: 关于iOS/iPhone中的文件选择对话框,用于用户去选择图片等文件 的过程中,遇到个问题,希望程序提供用户选择自己想要的图片作为Bird的图片. 但是当前开发环境是iOS模拟器,所 ...

  7. 打通前后端全栈开发node+vue进阶【课程学习系统项目实战详细讲解】(3):用户添加/修改/删除 vue表格组件 vue分页组件

    第三章 建议学习时间8小时      总项目预计10章 学习方式:详细阅读,并手动实现相关代码(如果没有node和vue基础,请学习前面的vue和node基础博客[共10章] 演示地址:后台:demo ...

  8. iOS运用runtime全局修改UILabel的默认字体

    iOS运用runtime全局修改UILabel的默认字体 一.需求背景介绍 在项目比较成熟的基础上,遇到了这样一个需求,应用中需要引入新的字体,需要更换所有Label的默认字体,但是同时,对于一些特殊 ...

  9. DOM学习笔记(三)DOM元素的访问、修改与事件

    访问 HTML 元素等同于访问节点,使用的是document对象下的数个getElement方法,然后再对返回的元素(或元素列表)进行具体内容的访问和修改,或者响应对应的事件是操作 一些 DOM 对象 ...

  10. Xamarin.Forms读取并展示Android和iOS通讯录 - TerminalMACS客户端

    Xamarin.Forms读取并展示Android和iOS通讯录 - TerminalMACS客户端 本文同步更新地址: https://dotnet9.com/11520.html https:// ...

随机推荐

  1. B. Divisors of Two Integers

    B. Divisors of Two Integers time limit per test 1 second memory limit per test 256 megabytes input s ...

  2. (转)博弈 SG函数

    此文为以下博客做的摘要: https://blog.csdn.net/strangedbly/article/details/51137432 ---------------------------- ...

  3. SQL语句练习45题(从第11题开始)

    CREATE TABLE student (sno VARCHAR(3) NOT NULL, sname VARCHAR(4) NOT NULL, ssex VARCHAR(2) NOT NULL, ...

  4. 转 C#对多个集合和数组的操作(合并,去重,判断)

    在开发过程中.数组和集合的处理是最让我们担心.一般会用for or foreach 来处理一些操作.这里介绍一些常用的集合跟数组的操作函数. 首先举例2个集合A,B. List<int> ...

  5. hcheck 脚本

    hcheck.sql - Script to Check for Known Problems in Oracle8i, Oracle9i, Oracle10g, Oracle 11g and Ora ...

  6. oracle 查看一个表中的记录是否被锁住

    SELECT a.object_id, a.session_id, b.object_nameFROM v$locked_object a, dba_objects bWHERE a.object_i ...

  7. 基于云计算的IaaS、PaaS、SaaS三种服务模式的区别

    Infrastructure-as-a-Service(IaaS) - 基础即设施服务 基础设施主要包括网络系统(networking).存储设备(storage).服务器(servers).虚拟化技 ...

  8. myeclipse更改后台代码不用重启tomcat的方法

    myeclipse更改后台代码不用重启tomcat的方法   方法1:在WebRoot下的META-INF文件夹中新建一个名为context.xml文件,里面添加如下内容(要区分大小写): <C ...

  9. 图解DTS和PTS

    由于把视频编码成I,B,P等帧,如下图   假设现在有I,B,P帧,那么要传输和显示呢??   如果按照显示顺序传输的话: 传输顺序就是I->B>P 当对B帧进行解码后,由于B帧无法单独显 ...

  10. 牛客网Java刷题知识点之HashMap的实现原理、HashMap的存储结构、HashMap在JDK1.6、JDK1.7、JDK1.8之间的差异以及带来的性能影响

    不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号:   大数据躺过的坑      Java从入门到架构师      人工智能躺过的坑          ...