IOS 通讯录 (访问,添加,修改)
如何访问用户的通讯录
在iOS中,有2个框架可以访问用户的通讯录
AddressBookUI.framework
提供了联系人列表界面、联系人详情界面、添加联系人界面等
一般用于选择联系人
AddressBook.framework
纯C语言的API,仅仅是获得联系人数据 没有提供UI界面展示,需要自己搭建联系人展示界面 里面的数据类型大部分基于Core Foundation框架,使用起来极其蛋疼
从iOS6开始,需要得到用户的授权才能访问通讯录,因此在使用之前,需要检 查用户是否已经授权
获得通讯录的授权状态: ABAddressBookGetAuthorizationStatus()
授权状态
● 用户还没有决定是否授权你的程序进行访问
➢ kABAuthorizationStatusRestricted
● iOS设备上的家长控制或其它一些许可配置阻止程序与通讯录数据库进行交互
➢ kABAuthorizationStatusDenied
● 用户明确的拒绝了你的程序对通讯录的访问
➢ kABAuthorizationStatusAuthorized
● 用户已经授权给你的程序对通讯录进行访问
申请访问通讯录
granted, CFErrorRef error) {
if (granted) {
NSLog(@"授权成功!"); } else {
NSLog(@"授权失败!"); }
});
CFRelease(addressBook);
提示:申请通讯录访问授权的代码,通常放在AppDelegate中
联系人属性定义
● 联系人属性包括以下类型:
● 简单属性:姓、名等
● 多重属性:电话号码、电子邮件等
● 组合属性:地址等
● 注意:使用ABRecordCopyValue可以从一条Person记录中
获取到对应的记录,但是后续处理则需要根据记录的具体
类型加以区分
简单属性
● 使用ABRecordCopyValue函数可以从ABRecordRef中获得联系人 的简单属性(例如:一个字符串)
● ABRecordCopyValue函数接收2个参数
● 第1个参数是ABRecordRef实例
● 第2个参数是属性关键字,定义在ABPerson.h中
● ABPersonCopyLocalizedPropertyName函数可以根据指定的关键
字获取对应的标签文本
获得所有的联系人数据
NSInteger count = CFArrayGetCount(array);
for (NSInteger i = 0; i < count; ++i) {
// 取出一条记录
ABRecordRef person =CFArrayGetValueAtIndex(array, i);
// 取出个人记录中的详细信息
// 名
CFStringRef firstNameLabel =ABPersonCopyLocalizedPropertyName(kABPersonFirstNameProperty);
CoreFoundation 与 Foundation之间的桥接
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil);
// 2. 获取所有联系人记录
NSArray *array = (__bridge NSArray *)(ABAddressBookCopyArrayOfAllPeople(addressBook));
// 取出一条记录
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 phoneNumber =ABMultiValueCopyValueAtIndex(phones, i);
添加联系人的步骤
2.通过ABRecordSetValue函数设置联系人的属性
3.通过ABAddressBookAddRecord函数将联系人添加到通讯录数据 库中
4.通过ABAddressBookSave函数保存刚才所作的修改
● 可以通过ABAddressBookHasUnsavedChanges函数判断是否有未保存
的修改
● 当决定是否更改通讯录数据库后,你可以分别使用AbAddressBookSave或 ABAddressBookRevert 方式来保存或放弃更改
添加群组的步骤
➢ 通过ABPersonCreate函数创建一个新的组(返回ABRecordRef)
➢ 通过ABRecordSetValue函数设置组名
➢ 通过ABAddressBookAddRecord函数将组添加到通讯录数
据库中
➢ 通过ABAddressBookSave函数保存刚才所作的修改
操作联系人的头像
● 判断通讯录中的联系人是否有图片
● 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 通讯录 (访问,添加,修改)的更多相关文章
- IOS开发笔记 IOS如何访问通讯录
IOS开发笔记 IOS如何访问通讯录 其实我是反对这类的需求,你说你读我的隐私,我肯定不愿意的. 幸好ios6.0 以后给了个权限控制.当打开app的时候你可以选择拒绝. 实现方法: [plain] ...
- iOS通讯录相关知识-浅析
本文来自于:贞娃儿的博客 http://blog.sina.com.cn/zhenwawaer 在开发一些应用中,我们如果需要iPhone设备中的通讯录信息.或者,需要开发通讯录相关的一些功能.那 ...
- 使用vscode访问和修改远程计算机文件
使用vscode访问和修改远程文件,分三步实现:在远程linux机器上安装rmate:在本地windows上安装openssh:在vscode中安装扩展remote vscode. 1. 在远程lin ...
- roundcute 添加修改密码插件
添加修改密码插件 现打开main.inc.php 文件,搜索“$rcmail_config['plugins']”,找到: // List of active plugins (in plugins/ ...
- ASP.NET MVC用存储过程批量添加修改数据
用Entity Framework 进行数据库交互,在代码里直接用lamda表达式和linq对数据库操作,中间为程序员省去了数据库访问的代码时间,程序员直接可以专注业务逻辑层的编写.但是对于比较复杂的 ...
- 向IOS模拟机上添加图片
[问题] 折腾: 关于iOS/iPhone中的文件选择对话框,用于用户去选择图片等文件 的过程中,遇到个问题,希望程序提供用户选择自己想要的图片作为Bird的图片. 但是当前开发环境是iOS模拟器,所 ...
- 打通前后端全栈开发node+vue进阶【课程学习系统项目实战详细讲解】(3):用户添加/修改/删除 vue表格组件 vue分页组件
第三章 建议学习时间8小时 总项目预计10章 学习方式:详细阅读,并手动实现相关代码(如果没有node和vue基础,请学习前面的vue和node基础博客[共10章] 演示地址:后台:demo ...
- iOS运用runtime全局修改UILabel的默认字体
iOS运用runtime全局修改UILabel的默认字体 一.需求背景介绍 在项目比较成熟的基础上,遇到了这样一个需求,应用中需要引入新的字体,需要更换所有Label的默认字体,但是同时,对于一些特殊 ...
- DOM学习笔记(三)DOM元素的访问、修改与事件
访问 HTML 元素等同于访问节点,使用的是document对象下的数个getElement方法,然后再对返回的元素(或元素列表)进行具体内容的访问和修改,或者响应对应的事件是操作 一些 DOM 对象 ...
- Xamarin.Forms读取并展示Android和iOS通讯录 - TerminalMACS客户端
Xamarin.Forms读取并展示Android和iOS通讯录 - TerminalMACS客户端 本文同步更新地址: https://dotnet9.com/11520.html https:// ...
随机推荐
- 处女座和他的小姐姐(三)----数位DP
链接:https://ac.nowcoder.com/acm/contest/329/G来源:牛客网 经过了选号和漫长的等待,处女座终于拿到了给小姐姐定制的手环,小姐姐看到以后直呼666! 处女座其实 ...
- 磁盘挂载 fdisk
fdisk -l 查看是否 已加入磁盘 fdisk /dev/sdb fdisk -cu /dev/sdb 取消兼容模式 添加一个硬盘,只创建一个分区,然后把分区挂载到/data 第 ...
- qs.parse()、qs.stringify()、JSON.parse()、JSON.stringify()使用方法
一.JSON.parse(用于从一个字符串中解析出json 对象)ps:单引号写在{}外,每个属性都必须双引号,否则会抛出异常 let str = '[{"field":" ...
- OSG DB的插件地址设置
今天搞了一整天OSG,结果每次都说could not find plugin,就是说找不到OSG的插件去加载文件,我大概看了下OSG的插件机制,发现他是用插件的形式下去读取文件的 http://blo ...
- 修改Android解锁界面
解锁界面效果类似如下 其实这也是我后面做出的效果,样机因为没有ROOT不好调试截图,功能是将解锁的图标添加了最近运行的运用的图标,这样的话更方便用户去使用 1.分析 1.1.Android锁屏功能分析 ...
- [Activator-HelloAkka] Define our Actors
The Actor is the unit of execution in Akka. Actors are object-oriented in the sense that they encaps ...
- mysql存储过程嵌套循环并分页处理数据
业务背景:公司存证产品升级,随着数据量的增加,存证产品线按业务分表,导致以往的存证关联数据需要做数据同步更新.版本发布前,通过当前存储过程解决数据升级问题. ##创建存证文档关联情况下更新所用存储过程 ...
- HDU 5289——Assignment——————【RMQ+优化求解】
Assignment Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- python学习(五)--打印错误信息
from urllib import request #打印错误信息 except Exceptionlist = [ "http://www.baidu11.com/", &qu ...
- Arcgis flex 切片地图麻点
在arcgis server中发布地图切片完成后,有时候在访问地图的时候会出现很多麻点, 其实是你切片的时候没有注意到一些选项.... 默认的切片是PNG8,说到这可能就明白了吧,png8的色彩范围: ...