首页 > 代码库 > IOS 通讯录 (访问,添加,修改)

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函数判断是否有未保存

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

 

添加群组的步骤

 

添加群组的步骤大体和添加联系人一致
? 通过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 = http://www.mamicode.com/(__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
View Code

 

实例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;
}
View Code

 

技术分享
#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 =http://www.mamicode.com/ 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 = http://www.mamicode.com/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
View Code

 

 

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