通讯录

来源:互联网 发布:pl sql mysql 编辑:程序博客网 时间:2024/05/01 03:47

AddressBook

iOS中带有一个Contacts应用程序来管理联系人,但是有些时候我们希望自己的应用能够访问或者修改这些信息,这个时候就要用到 AddressBook.framework框架。iOS中的通讯录是存储在数据库中的,由于iOS的权限设计,开发人员是不允许直接访问通讯录数据库 的,必须依靠AddressBook提供的标准API来实现通讯录操作。通过AddressBook.framework开发者可以从底层去操作 AddressBook.framework的所有信息,但是需要注意的是这个框架是基于C语言编写的,无法使用ARC来管理内存,开发者需要自己管理内 存。下面大致介绍一下通讯录操作中常用的类型:

  • ABAddressBookRef:代表通讯录对象,通过该对象开发人员不用过多的关注通讯录的存储方式,可以直接以透明的方式去访问、保存(在 使用AddressBook.framework操作联系人时,所有的增加、删除、修改后都必须执行保存操作,类似于Core Data)等。
  • ABRecordRef:代表一个通用的记录对象,可以是一条联系人信息,也可以是一个群组,可以通过 ABRecordGetRecordType()函数获得具体类型。如果作为联系人(事实上也经常使用它作为联系人),那么这个记录记录了一个完整的联系 人信息(姓名、性别、电话、邮件等),每条记录都有一个唯一的ID标示这条记录(可以通过ABRecordGetRecordID()函数获得)。
  • ABPersonRef:代表联系人信息,很少直接使用,实际开发过程中通常会使用类型为“kABPersonType”的ABRecordRef来表示联系人(由此可见ABPersonRef其实是一种类型为“kABPersonType”的ABRecordRef)
  • ABGroupRef:代表群组,与ABPersonRef类似,很少直接使用ABGroupRef,而是使用类型为“kABGroupType”的ABRecordRef来表示群组,一个群组可以包含多个联系人,一个联系人也同样可以多个群组。

由于通讯录操作的关键是对ABRecordRef的操作,首先看一下常用的操作通讯录记录的方法:

ABPersonCreate():创建一个类型为“kABPersonType”的ABRecordRef。

ABRecordCopyValue():取得指定属性的值。

ABRecordCopyCompositeName():取得联系人(或群组)的复合信息(对于联系人则包括:姓、名、公司等信息,对于群组则返回组名称)。

ABRecordSetValue():设置ABRecordRef的属性值。注意在设置ABRecordRef的值时又分为单值属性和多值属性: 单值属性设置只要通过ABRecordSetValue()方法指定属性名和值即可;多值属性则要先通过创建一个 ABMutableMultiValueRef类型的变量,然后通过ABMultiValueAddValueAndLabel()方法依次添加属性值, 最后通过ABRecordSetValue()方法将ABMutableMultiValueRef类型的变量设置为记录值。

ABRecordRemoveValue():删除指定的属性值。

注意:

由于联系人访问时(读取、设置、删除时)牵扯到大量联系人属性,可以到ABPerson.h中查询或者直接到帮助文档“Personal Information Properties”

通讯录的访问步骤一般如下:

  • 调用ABAddressBookCreateWithOptions()方法创建通讯录对象ABAddressBookRef。

  • 调用ABAddressBookRequestAccessWithCompletion()方法获得用户授权访问通讯录。

  • 调用ABAddressBookCopyArrayOfAllPeople()、ABAddressBookCopyPeopleWithName()方法查询联系人信息。

  • 读取联系人后如果要显示联系人信息则可以调用ABRecord相关方法读取相应的数据;如果要进行修改联系人信息,则可以使用对应的方 法修改ABRecord信息,然后调用ABAddressBookSave()方法提交修改;如果要删除联系人,则可以调用 ABAddressBookRemoveRecord()方法删除,然后调用ABAddressBookSave()提交修改操作。

  • 也就是说如果要修改或者删除都需要首先查询对应的联系人,然后修改或删除后提交更改。如果用户要增加一个联系人则不用进行查询,直接调 用ABPersonCreate()方法创建一个ABRecord然后设置具体的属性,调用ABAddressBookAddRecord方法添加即可。

下面就通过一个示例演示一下如何通过ABAddressBook.framework访问通讯录,这个例子中通过一个UITableViewController模拟一下通讯录的查看、删除、添加操作。

主控制器视图,用于显示联系人,修改删除联系人:

KCContactViewController.h

//
// KCTableViewController.h
// AddressBook
//
// Created by Kenshin Cui on 14/04/05.
// Copyright (c) 2014年 cmjstudio. All rights reserved.
//

import

import “KCContactTableViewController.h”

import

import “KCAddPersonViewController.h”

@interface KCContactTableViewController ()

@property (assign,nonatomic) ABAddressBookRef addressBook;//通讯录
@property (strong,nonatomic) NSMutableArray *allPerson;//通讯录所有人员

@property (assign,nonatomic) int isModify;//标识是修改还是新增,通过选择cell进行导航则认为是修改,否则视为新增
@property (assign,nonatomic) UITableViewCell *selectedCell;//当前选中的单元格

@end

@implementation KCContactTableViewController

pragma mark - 控制器视图

  • (void)viewDidLoad {
    [super viewDidLoad];

    //请求访问通讯录并初始化数据
    [self requestAddressBook];
    }

//由于在整个视图控制器周期内addressBook都驻留在内存中,所有当控制器视图销毁时销毁该对象
-(void)dealloc{
if (self.addressBook!=NULL) {
CFRelease(self.addressBook);
}
}

pragma mark - UI事件

//点击删除按钮
- (IBAction)trashClick:(UIBarButtonItem *)sender {
self.tableView.editing=!self.tableView.editing;
}

pragma mark - UITableView数据源方法

  • (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
    }

  • (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.allPerson.count;
    }

  • (UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *identtityKey=@”myTableViewCellIdentityKey1”;
    UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:identtityKey];
    if(cell==nil){
    cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identtityKey];
    }
    //取得一条人员记录
    ABRecordRef recordRef=(__bridge ABRecordRef)self.allPerson[indexPath.row];
    //取得记录中得信息
    NSString firstName=(__bridge NSString ) ABRecordCopyValue(recordRef, kABPersonFirstNameProperty);//注意这里进行了强转,不用自己释放资源
    NSString lastName=(__bridge NSString )ABRecordCopyValue(recordRef, kABPersonLastNameProperty);

    ABMultiValueRef phoneNumbersRef= ABRecordCopyValue(recordRef, kABPersonPhoneProperty);//获取手机号,注意手机号是ABMultiValueRef类,有可能有多条
    // NSArray phoneNumbers=(__bridge NSArray )ABMultiValueCopyArrayOfAllValues(phoneNumbersRef);//取得CFArraryRef类型的手机记录并转化为NSArrary
    long count= ABMultiValueGetCount(phoneNumbersRef);
    // for(int i=0;i

pragma mark - UITableView代理方法

-(void)tableView:(UITableView )tableView didSelectRowAtIndexPath:(NSIndexPath )indexPath{
self.isModify=1;
self.selectedCell=[tableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:@”AddPerson” sender:self];
}

pragma mark - Navigation

  • (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue.identifier isEqualToString:@”AddPerson”]){
    UINavigationController navigationController=(UINavigationController )segue.destinationViewController;
    //根据导航控制器取得添加/修改人员的控制器视图
    KCAddPersonViewController addPersonController=(KCAddPersonViewController )navigationController.topViewController;
    addPersonController.delegate=self;
    //如果是通过选择cell进行的导航操作说明是修改,否则为添加
    if (self.isModify) {
    UITableViewCell *cell=self.selectedCell;
    addPersonController.recordID=(ABRecordID)cell.tag;//设置
    NSArray *array=[cell.textLabel.text componentsSeparatedByString:@” “];
    if (array.count>0) {
    addPersonController.firstNameText=[array firstObject];
    }
    if (array.count>1) {
    addPersonController.lastNameText=[array lastObject];
    }
    addPersonController.workPhoneText=cell.detailTextLabel.text;

    }

    }
    }

pragma mark - KCContact代理方法

-(void)editPersonWithFirstName:(NSString )firstName lastName:(NSString )lastName workNumber:(NSString *)workNumber{
if (self.isModify) {
UITableViewCell *cell=self.selectedCell;
NSIndexPath *indexPath= [self.tableView indexPathForCell:cell];
[self modifyPersonWithRecordID:(ABRecordID)cell.tag firstName:firstName lastName:lastName workNumber:workNumber];
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];
}else{
[self addPersonWithFirstName:firstName lastName:lastName workNumber:workNumber];//通讯簿中添加信息
[self initAllPerson];//重新初始化数据
[self.tableView reloadData];
}
self.isModify=0;
}
-(void)cancelEdit{
self.isModify=0;
}

pragma mark - 私有方法

/**
* 请求访问通讯录
*/
-(void)requestAddressBook{
//创建通讯录对象
self.addressBook=ABAddressBookCreateWithOptions(NULL, NULL);

//请求访问用户通讯录,注意无论成功与否block都会调用ABAddressBookRequestAccessWithCompletion(self.addressBook, ^(bool granted, CFErrorRef error) {    if (!granted) {        NSLog(@"未获得通讯录访问权限!");    }    [self initAllPerson];});

}
/**
* 取得所有通讯录记录
*/
-(void)initAllPerson{
//取得通讯录访问授权
ABAuthorizationStatus authorization= ABAddressBookGetAuthorizationStatus();
//如果未获得授权
if (authorization!=kABAuthorizationStatusAuthorized) {
NSLog(@”尚未获得通讯录访问授权!”);
return ;
}
//取得通讯录中所有人员记录
CFArrayRef allPeople= ABAddressBookCopyArrayOfAllPeople(self.addressBook);
self.allPerson=(__bridge NSMutableArray *)allPeople;

//释放资源CFRelease(allPeople);

}

/**
* 删除指定的记录
*
* @param recordRef 要删除的记录
*/
-(void)removePersonWithRecord:(ABRecordRef)recordRef{
ABAddressBookRemoveRecord(self.addressBook, recordRef, NULL);//删除
ABAddressBookSave(self.addressBook, NULL);//删除之后提交更改
}
/**
* 根据姓名删除记录
*/
-(void)removePersonWithName:(NSString *)personName{
CFStringRef personNameRef=(__bridge CFStringRef)(personName);
CFArrayRef recordsRef= ABAddressBookCopyPeopleWithName(self.addressBook, personNameRef);//根据人员姓名查找
CFIndex count= CFArrayGetCount(recordsRef);//取得记录数
for (CFIndex i=0; i

import

import “KCAddPersonViewController.h”

import “KCContactTableViewController.h”

@interface KCAddPersonViewController ()

@property (weak, nonatomic) IBOutlet UITextField *firstName;
@property (weak, nonatomic) IBOutlet UITextField *lastName;
@property (weak, nonatomic) IBOutlet UITextField *workPhone;
@end

@implementation KCAddPersonViewController

  • (void)viewDidLoad {
    [super viewDidLoad];
    [self setupUI];
    }

pragma mark - UI事件

  • (IBAction)cancelClick:(UIBarButtonItem *)sender {
    [self.delegate cancelEdit];
    [self dismissViewControllerAnimated:YES completion:nil];
    }

  • (IBAction)doneClick:(UIBarButtonItem *)sender {
    //调用代理方法
    [self.delegate editPersonWithFirstName:self.firstName.text lastName:self.lastName.text workNumber:self.workPhone.text];

    [self dismissViewControllerAnimated:YES completion:nil];
    }

pragma mark - 私有方法

-(void)setupUI{
if (self.recordID) {//如果ID不为0则认为是修改,此时需要初始化界面
self.firstName.text=self.firstNameText;
self.lastName.text=self.lastNameText;
self.workPhone.text=self.workPhoneText;
}
}
@end

0 0
原创粉丝点击