IOS 通讯录 (访问,添加,修改)

如何访问用户的通讯录

在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 = 0; 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 = 0; 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

时间: 2024-10-05 10:52:58

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

IOS Ui控件 修改位置和尺寸,代码添加控件

所有的UI控件最终都继承自UIView,UI控件的公共属性都定义在UIView中, UIView的常见属性 UIView *superview; 获得自己的父控件对象 NSArray *subviews; 获得自己的所有子控件对象 NSInteger tag; 控件的ID(标识),父控件可以通过tag来找到对应的子控件 CGAffineTransform transform; 控件的形变属性(可以设置旋转角度.比例缩放.平移等属性) CGRect frame; 控件所在矩形框在父控件中的位置和尺

iOS通讯录相关知识-浅析

本文来自于:贞娃儿的博客  http://blog.sina.com.cn/zhenwawaer 在开发一些应用中,我们如果需要iPhone设备中的通讯录信息.或者,需要开发通讯录相关的一些功能.那么就需要了解一下iOS中关于通讯录编程的相关知识. 一.AddressBook.framework-通讯录框架 关于通讯录的相关操作,被集成在AddressBook.framework框架中.所以,我们在使用通讯录相关功能的时候,需要在项目中引入AddressBook.framework框架.并且在需

iOS: 学习笔记, 添加一个带界面约束的控制器

1. 创建一个空iOS应用程序(Empty Application). 2. 添加加控制器类. 修改控制器类的viewDidLoad 1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 //创建标题 5 UILabel *header = [[UILabel alloc] init]; 6 header.text = @"欢迎来到我的世界!"; 7 header.textAlignment = NSTextAlignmentCenter

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

用Entity Framework 进行数据库交互,在代码里直接用lamda表达式和linq对数据库操作,中间为程序员省去了数据库访问的代码时间,程序员直接可以专注业务逻辑层的编写.但是对于比较复杂的表关系关联查询或者修改就比较费劲了.通常可以采用的方式是用EF执行SQL语句或者"存储过程",特别是执行复杂批量任务,当然也可以在MVC底层用ADO.NET,这里就不多说了.怎么做批量呢?这里讲讲在EF下用存储过程批量添加修改数据. 需求是这样的:需要批量添加修改产品类别的投放任务数额,每

IOS网络访问之使用AFNetworking

IOS网络访问之使用AFNetworking AFNetworking是IOS上常用的第三方网络访问库,我们可以在github上下载它,同时github上有它详细的使用说明,最新的AFNetworing2.0与1.0有很大的变化,这里仅对2.0常用的使用方法进行总结 基于NSURLConnection的API 提交GET请求 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [man

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

使用vscode访问和修改远程文件,分三步实现:在远程linux机器上安装rmate:在本地windows上安装openssh:在vscode中安装扩展remote vscode. 1. 在远程linux机器上安装rmate rmate有很多中语言版本,这里用的是python的版本.github地址:https://github.com/sclukey/rmate-python 下载安装比较简单,在linux中执行以下命令即可 wget https://raw.githubusercontent

roundcute 添加修改密码插件

添加修改密码插件 现打开main.inc.php 文件,搜索“$rcmail_config['plugins']”,找到: // List of active plugins (in plugins/ directory) $rcmail_config['plugins'] = array(); 这里我想添加修改密码功能,修改代码如下: // List of active plugins (in plugins/ directory) $rcmail_config['plugins'] = ar

SQL应用与开发:(七)数据操作 &#183; 查 &#183; (三)使用子查询访问和修改数据

3.使用子查询访问和修改数据 子查询和连接查询一样提供了使用单个查询访问多个表中的数据的方法.子查询在其他结果的基础上提供一种有效地方式来表示WHERE子句的条件.子查询是一个SELECT语句,它定义在SELECT.INSERT.UPDATE或DELECT语句或者另一个子查询中.子查询的SELECT语句可与外部查询指向不同的表. 嵌套的子查询或嵌套的SELECT语句是指包含一个或多个子查询的SELECT语句.子查询可嵌套在外部的SELECT.INSERT.UPDATE或DELECT语句的WHER

IOS网络访问之使用AFNetworking&lt;2&gt;

IOS网络访问之使用AFNetworking AFNetworking是IOS上常用的第三方网络访问库,我们可以在github上下载它,同时github上有它详细的使用说明,最新的AFNetworing2.0与1.0有很大的变化,这里仅对2.0常用的使用方法进行总结 基于NSURLConnection的API 提交GET请求 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [man

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

iOS运用runtime全局修改UILabel的默认字体 一.需求背景介绍 在项目比较成熟的基础上,遇到了这样一个需求,应用中需要引入新的字体,需要更换所有Label的默认字体,但是同时,对于一些特殊设置了字体的label又不需要更换.乍看起来,这个问题确实十分棘手,首先项目比较大,一个一个设置所有使用到的label的font工作量是巨大的,并且在许多动态展示的界面中,可能会漏掉一些label,产生bug.其次,项目中的label来源并不唯一,有用代码创建的,有xib和storyBoard中的,