iOS框架—使用地址簿

一、为何支持地址簿很重要:

当开发iOS软件的时候,就与用户的移动生活建立了联系。用户走到哪里都带着移动设备,可以说移动设备与用户的个人生活(从日历到个人相册)休戚相关。在这种移动生活中,通讯录占据着重要的位置。应用可以使用联系人数据库确定用户是否有朋友注册了相关服务:分析联系人的电子邮件地址或电话号码,并将联系人自动添加为好友。应用还可以使用联系人列表自动填写邮件地址或电话号码,或让用户通过蓝牙与朋友分享联系人信息。应用需要访问用户通讯录的原因不胜枚举。

注意:

除非有充分的理由,否则不要访问联系人数据库,这很重要,因为没有什么比泄露隐私更能让用户毅然决然地放弃使用您的应用了。

二、使用地址簿

想要使用地址簿框架,需要先将两个有关地址薄的框架导入到项目中:AddressBookUI.framework和AddressBook.framework。其中前者提供了选择、编辑和显示联系人的图形用户界面,而后者是让您能够与联系人数据交互。然后在相关的类中导入头文件,如下所示:

#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>

首先,我在项目中创建了两个类的属性:addressBook和addressBookEntryArray

@property (nonatomic, assign) ABAddressBookRef addressBook;
@property (nonatomic, strong) NSMutableArray *addressBookEntryArray;

addressBookEntryArray是用来存储获取到的系统中的地址薄条目数组。

注意:

将地址薄复制到内存的开销极高,因此应最大限度地减少这种操作的次数。

在使用地址簿的时候,我们应该获取访问手机中地址薄的权限:

//申请访问权限
ABAddressBookRequestAccessWithCompletion(_addressBook, ^(bool greanted, CFErrorRef error) {

    //greanted为YES是表示用户允许,否则为不允许
    if (!greanted) {
        NSLog(@"未取得权限");
    }
});

接下来,创建一个地址薄的引用:

CFErrorRef error = NULL;

//创建通讯簿的引用
_addressBook = ABAddressBookCreateWithOptions(nil, &error);

在创建地址薄引用的时候现在最好用ABAddressBookCreateWithOptions这个方法,原来的
ABAddressBookCreate已经作废。

AB_EXTERN ABAddressBookRef ABAddressBookCreateWithOptions(CFDictionaryRef options, CFErrorRef* error) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_6_0);

AB_EXTERN ABAddressBookRef ABAddressBookCreate(void) __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA,__MAC_NA,__IPHONE_2_0,__IPHONE_6_0);

由上面的代码可以看出,
ABAddressBookCreate支持的版本是iOS 2.0 到 iOS 6.0,在开发iOS 6.0 之后系统的时候应该使用
ABAddressBookCreateWithOptions去创建地址薄的引用。

_addressBookEntryArray = (__bridge NSMutableArray *)ABAddressBookCopyArrayOfAllPeople(_addressBook);

创建了地址薄的引用后,就要将手机地址薄中的联系人拷贝到数组addressBookEntryArray中,这里,我拷贝了所有联系人的信息,其他的拷贝方式请自行查看API文档。在获取所有联系人之前需要考虑到地址薄为空的情形,这种情况下给用户一个良好的提示,让用户知道APP没有出错崩溃,这里我用了一个alert弹窗来简单的显示提示信息。

if(ABAddressBookGetPersonCount(_addressBook) == 0) {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"联系人为空"
                                                        message:@""
                                                       delegate:nil
                                              cancelButtonTitle:@"确定"
                                              otherButtonTitles: nil];
    [alertView show];
}

在读到地址薄中联系人信息后,这里将获得的数据展示在了一个tableviewcontroller中。

三、从地址簿中读取数据

读入到addressBookEntryArray数组中的每一个条目都是一个ABRecordRef,单值数据可以用方法ABRecordCopyValue方法读取:

ABRecordRef record = (__bridge ABRecordRef)([_addressBookEntryArray objectAtIndex:indexPath.row]);
CFStringRef firstName = ABRecordCopyValue(record, kABPersonFirstNameProperty);
CFStringRef lastName = ABRecordCopyValue(record, kABPersonLastNameProperty);

这里获取了联系人中的firstName和lastName。

ABRecordRef的所有单值属性如下表所示:

属性名 描述
kABPersonFirstNameProperty
kABPersonLastNameProperty
kABPersonMiddleNameProperty 中间名或所写
kABPersonPrefixProperty 姓名前缀(Mr.、Ms.、Dr.)
kABPersonSuffixProperty 姓名后缀(MD、Jr、Sr.)
kABPersonNicknameProperty 别名
kABPersonFirstNamePhoneticProperty 名字的读音
kABPersonLastNamePhoneticProperty 姓的读音
kABPersonMiddleNamePhoneticProperty 中间名读音
kABPersonOrganizationProperty 公司或组织
kABPersonJobTitleProperty 职务
kABPersonDepartmentProperty 部门
kABPersonEmailProperty 邮箱地址
kABPersonBirthdayProperty CFDate格式的生日,可自由桥接到NSDate
kABPersonNoteProperty 备注
kABPersonCreationDateProperty CFDate格式的创建日期
kABPersonModificationDateProperty CFDate格式的最后修改日期

四、从地址薄读取多值数据

当从地址薄中读取多值数据,例如:电话号码、电子邮件地址和街道地址这些数据时,需要用到ABMultiValueRef。这里展示了如何操作地址薄中的地址(地址是一个比较特殊的多值数据,因为取出来的是一个字典类型的数据):

//  通讯录地址的使用
ABMultiValueRef addressMulti = ABRecordCopyValue(record, kABPersonAddressProperty);
NSString *address = nil;
NSString *street = nil;
NSString *city = nil;
NSString *state = nil;
NSString *zip = nil;
if (ABMultiValueGetCount(addressMulti) > 0) {
    NSDictionary *addressDictionary = (__bridge NSDictionary *)(ABMultiValueCopyValueAtIndex(addressMulti, 0));
    street = [addressDictionary objectForKey:(NSString *)kABPersonAddressStreetKey];
    city = [addressDictionary objectForKey:(NSString *)kABPersonAddressCityKey];
    state = [addressDictionary objectForKey:(NSString *)kABPersonAddressStateKey];
    zip = [addressDictionary objectForKey:(NSString *)kABPersonAddressZIPKey];
}

address = [NSString stringWithFormat: @"%@ %@ %@ %@", street, city, state, zip];

从API中得知,地址是一个字典类型的值。首先将地址取出,然后在转换成字典,用API中对应的Key去获得对应的数据。

地址的组成部分由下表所示:

属性 描述
kABPersonAddressStreetKey 街道名和门牌号(包括房间号)
kABPersonAddressCityKey 城市名
kABPersonAddressStateKey 两字符州名或完整的州名
kABPersonAddressZIPKey 邮政编码(5位或者9位数字)
kABPersonAddressCountryKey 完整的国家名
kABPersonAddressCountryCodeKey 两字符国别码

五、地址标签的使用

在通过多值获取到电话号码后,使用的是电话号码的索引号。虽然电话号码索引对开发人员很有用,但是对用户来说毫无意义,因此这里使用地址标签获取到联系人使用的标签。要获取多值引用的标签,首先需要调用ABMultiValueCopyLabelAtIndex。调用这个函数时,使用的参数与获取多值对象的值时相同。这个函数返回一个未经本地化的字符串如:_$!<Mobile>!$_。虽然这个字符串比索引号有用的多,但还是不太合适显示给用户。为获得用户能看明白的字符串,需要将返回的标签进行本地化。为此,可调用ABAddressBookCopyLocalizedLabel,并将刚返回的CFStringRef作为参数。代码中我获取了电话号码的标签,并输出到后台:

//  读取多个值的方法
ABMultiValueRef phoneNumbers = ABRecordCopyValue(record, kABPersonPhoneProperty);

if (ABMultiValueGetCount(phoneNumbers) > 0) {
    for (int i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
//    第二个参数是获取电话号码的类型,例如:手机,家庭电话等(地址簿标签)
        NSLog(@"%@ [%@]", ABMultiValueCopyValueAtIndex(phoneNumbers, i), ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(phoneNumbers, i)));
    }
}

六、联系人选择器

联系人选择器创建一个像系统内置的地址薄中的联系人选择器类似的一个界面。首先这个类需要遵守协议ABPeoplePickerNavigationControllerDelegate,然后使用如下的代码创建一个选择控制器。

ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentViewController:picker animated:YES completion:nil];

选择器创建完成后,这里有三个委托方法,在用户与联系人选择器交互时做出相应。第一个方法是对用户“取消”按钮做出响应:

- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {

    [self dismissViewControllerAnimated:YES completion:nil];
}

第二个委托方法是告诉联系人选择器,您不想让用户选择联系人的具体属性,即用户无法通过联系人选择器查看到联系人的详细信息。当用户选择一个联系人后,联系人选择器就会自动dismiss掉。

// 此方法选择联系人后,不能跳转到详细页面,即不能读取详细信息
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person {

    NSLog(@"You have selected: %@", ABRecordCopyValue(person, kABPersonFirstNameProperty));
}

第三个委托方法实现后,用户可以查看联系人的详细信息。

// 可以获取联系人的详细信息
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {

    NSLog(@"Person: %@, Property: %i, Identifier: %i", person, property, identifier);
}

这里我们还可以定制联系人选择器进入详细页面后所能访问的内容,在创建联系人选择器后,加入下面的代码用户进入详细页面后只能查看联系人的电话号码:

picker.displayedProperties = [NSArray arrayWithObject: [NSNumber numberWithInt:kABPersonPhoneProperty]];

六、使用ABPersonViewController编辑和查看联系人

大多数的情况下,都使用内置的地址薄用户界面来显示或编辑联系人。在此代码中,将联系人信息显示在了一个tableview中,选中cell后将跳转到一个ABPersonViewController页面进行联系人详细信息的查看。

ABPersonViewController *personViewController = [[ABPersonViewController alloc] init];
ABRecordRef record = (__bridge ABRecordRef)([_addressBookEntryArray objectAtIndex:indexPath.row]);
personViewController.personViewDelegate = self;
personViewController.displayedPerson = record;
personViewController.allowsEditing = YES;
personViewController.allowsActions = NO;
[self.navigationController pushViewController:personViewController animated:YES];

这里的allowsEditing属性,是设置进入详细页面后,是否能够编辑联系人信息。

七、使用ABNewPersonViewController新建联系人

ABNewPersonViewController *newPersonController = [[ABNewPersonViewController alloc] init];
newPersonController.newPersonViewDelegate = self;
[self.navigationController pushViewController:newPersonController animated:YES];

当用户保存联系人时,会调用一个委托方法。在这个方法中,确定返回的联系人对象有效后,会依次调用ABAddressBookAddRecord和ABAddressBookSave将联系人保存到地址薄。

- (void)newPersonViewController:(ABNewPersonViewController *)newPersonView didCompleteWithNewPerson:(ABRecordRef)person {
    if (person) {
        CFErrorRef error = NULL;
        ABAddressBookAddRecord(_addressBook, person, &error);
        ABAddressBookSave(_addressBook, &error);
        if (error != NULL) {
            NSLog(@"An error occurred");
        }
    }
    _addressBookEntryArray = (__bridge NSMutableArray *)ABAddressBookCopyArrayOfAllPeople(_addressBook);
    [self.tableView reloadData];
    [self.navigationController popToRootViewControllerAnimated:YES];
}
时间: 2024-08-06 11:58:43

iOS框架—使用地址簿的相关文章

iOS:访问地址薄

地址簿的访问 介绍: 地址簿(Address Book)是一个共享的联系人信息数据库.任何iOS应用程序都可以使用.通过提供常用联系人信息,而不是让每一个应用程序管理独立的联系人列表,可改善用户体验.在拥有共享的地址簿后,无需在不同的应用程序中添加联系人多次,在一个应用程序中更新联系人信息后,其他所有应用程序就立刻能够使用它们.iOS通过两个框架提供了全面的地址簿数据库访问功能,分别是Address Book和Address Book UI. Address Book UI框架是一组用户界面类,

iOS框架介绍(三)---Cocoa Touch 层(转)

目录 Cocoa Touch 层 高级特性 多任务 数据保护 苹果推送通知服务 本地通知 手势识别器 文件共享支持 点对点服务 标准系统视图控制器 外部设备支持 Cocoa Touch 层包含的框架 Address Book UI 框架 Event Kit UI 框架 Game Kit 框架 iAd 框架 Map Kit 框架 Message UI 框架 UIKit 框架 Cocoa Touch 层 Cocoa Touch层包含创建 iOS应用程序所需的关键框架.上至实现应用程序可视界面,下至与

GPUImage ==&gt; 一个基于GPU图像和视频处理的开源iOS框架

Logo 项目介绍: GPUImage是Brad Larson在github托管的开源项目. GPUImage是一个基于GPU图像和视频处理的开源iOS框架,提供各种各样的图像处理滤镜,并且支持照相机和摄像机的实时滤镜: 基于GPU的图像加速,因此可以加速对实时摄像头视频.电影以及image的滤镜和其它效果处理,并且能够自定义图像滤镜.另外, GPUImage支持ARC. 使用GPUImage处理图片比Core Image更简单,只需要将过滤器赋给图片对象即可,不用考虑context或者设备等其

Webrtc的ios框架编译

1.WebRTC的iOS框架的选择 目前两个比较活跃的开源WebRTC实现. Google WebRTC: 项目地址是: https://code.google.com/p/webrtc/ Ericsson Research OpenWebRTC: 项目地址是: https://github.com/EricssonResearch/openwebrtc 我们戴维营教育为了给学生实战项目中运用WebRTC视频通话技术,选择Google的WebRTC项目来构建iOS App的开发框架,因为目前Ch

python 地址簿

创建你自己的命令行 地址簿 程序.在这个程序中,你可以添加.修改.删除和搜索你的联系人(朋友.家人和同事等等)以及它们的信息(诸如电子邮件地址和/或电话号码) #!/usr/bin/python # Filename : var.py import cPickle as p import os import sys filename = 'contacts.data' class member: def __init__(self, name, address, tel): self.name

用 eric6 与 PyQt5 实现python的极速GUI编程(系列04)---- PyQt5自带教程:地址簿(address book)

[引子] 在PyQt5自带教程中,地址簿(address book)程序没有完全实现界面与业务逻辑分离. 本文我打算用eric6+PyQt5对其进行改写,以实现界面与逻辑完全分离. [概览] 1.界面: 2.功能简介:程序有三种操作模式:浏览模式.添加模式.编辑模式. 其实现的功能都显式的体现在各个按钮上 3.主要步骤:1).在eric6中新建项目,新建窗体,取名为 addressbook.ui 文件 2).(自动打开)进入PyQt5 Desinger,编辑图形界面,保存 3).回到eric 6

IOS框架概览

iOS是运行在iPhone.iPod Touch或iPad上的操作系统,之前叫做iPhone OS,iOS与Mac OS X有共同的基础架构和底层技术.但iOS是根据移动设备的特点而设计的,所以和Mac OS X系统略有区别,比如对多点触摸和加速感应器的支持. 下面来看看iOS框架简介: iOS 的系统架构分为四个层次:核心操作系统层(Core OS layer).核心服务层(Core Services layer).媒体层(Media layer)和可触摸层(Cocoa Touch layer

供应商和管理员查看供应商地址簿信息SQL

--管理员查看地址簿 SELECT hps.party_site_id, hps.party_site_name AS address_name, 'CURRENT' AS status, hzl.address1 AS loc_address1, hzl.address2 AS loc_address2, hzl.address3 AS loc_address3, hzl.city AS loc_city, hzl.county AS loc_county, hzl.state AS loc_

Exchange 2013与Exchange 2016 HAB分层地址簿微小区别

最近测试了一下Exchange 2013和Exchange 2016两个版本的HAB功能,两个版本的配置方法均没有什么差别.至于如何配置HAB,我在之前的Blog中已经专门讲解过,可以浏览之前的文章. 配置了HAB后在OUtlook中查看到的效果如下: 今天我要将的是其他方面,通过我的测试我发现Exchange 2013以前的版本Outlook访问通讯簿中的HAB的方式是在线的,如果客户端断网或者与Exchange服务器中断连接了则无法打开HAB.然而Exchange 2016中Outlook访