如何访问用户的通讯录

在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. python3.6 request模块和ddt模块的安装

    1.1用cmd命令进到python的安装目录的Scripts文件夹 1.2.然后输入 pip install requests,出现以下提示,说明安装成功 2.安装ddt步骤一样,只是把pip ins ...

  2. C/S架构与B/S架构的区别

    什么是C/S结构和B/S结构? C/S结构 C/S结构是指Client/Server (客户机/服务器) 结构,是大家熟知的软件系统体系结构,通过将任务合理分配到Client端和Server端,降低了 ...

  3. (转)Shell中read的用法详解

    Shell中read的用法详解 原文:http://blog.csdn.net/jerry_1126/article/details/77406500 read的常用用法如下: read -[pstn ...

  4. css3之transition、transform、animation比较

    css3动画多少都有些了解,但是对于transition.transform.animation这几个属性一直是比较模糊的,所以啊,这里做一个总结,也希望大家都可以对此有一个更好地理解.    其实, ...

  5. FZU 2213——Common Tangents——————【两个圆的切线个数】

    Problem 2213 Common Tangents Accept: 7    Submit: 8Time Limit: 1000 mSec    Memory Limit : 32768 KB ...

  6. URAL —— 1255 & HDU 5100——Chessboard ——————【数学规律】

    用 k × 1 的矩形覆盖 n × n 的正方形棋盘 用 k × 1 的小矩形覆盖一个 n × n 的正方形棋盘,往往不能实现完全覆盖(比如,有时候 n × n 甚至根本就不是 k 的整倍数). 解题 ...

  7. SpringSecurity 3.2入门(10)自定义权限控制认证及授权的过程

    上一章的代码实现还存在一些问题,如角色表.权限表的用处没有体现出来,但是已经能完成URL拦截功能,后面将会继续完善认证及授权的过程. 认证及授权的过程如下: 1.容器启动,MyInvocationSe ...

  8. Sql server 0x80131904

    这是一个比较让人纠结的错误. 背景:添加了网站的分支,要拿一个现有的数据库做一个新的数据库的东东. 首先就是还原备份,然后做代码的修改.然而在登录的时候报了这个错误.0x80131904 什么插入的列 ...

  9. ireport 导出excel 分页 和 文本转数字格式的解决方法

    景:ireport 画excel 报表,导出时要求 数据分页,每页包含 标题和页脚 1.画excel 2.处理分页 首先建立一个变量totalNum 用于记录总共有多少条记录,注意设置属性为Integ ...

  10. 使用canvas及js简单生成验证码方法

    在很多时候都需要用到验证码,前端验证码需要知道Html5中的canvas知识点.验证码生成步骤是:1.生成一张画布canvas 2.生成随机数验证码  3.在画布中生成干扰线  4.把验证码文本填充到 ...