通讯录
来源:互联网 发布:mac os 最新版本 .cdr 编辑:程序博客网 时间:2024/05/01 01:52
通讯录AddressBookiOS中带有一个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 <UIKit/UIKit.h>/** * 定义一个协议作为代理 */@protocol KCContactDelegate//新增或修改联系人-(void)editPersonWithFirstName:(NSString *)firstName lastName:(NSString *)lastName workNumber:(NSString *)workNumber;//取消修改或新增-(void)cancelEdit;@end@interface KCContactTableViewController : UITableViewController@endKCContactViewController.m//// KCTableViewController.m// AddressBook//// Created by Kenshin Cui on 14/04/05.// Copyright (c) 2014年 cmjstudio. All rights reserved.//#import "KCContactTableViewController.h"#import <AddressBook/AddressBook.h>#import "KCAddPersonViewController.h"@interface KCContactTableViewController ()<KCContactDelegate>@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<count;++i){// NSString *phoneLabel= (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(phoneNumbersRef, i));// NSString *phoneNumber=(__bridge NSString *)(ABMultiValueCopyValueAtIndex(phoneNumbersRef, i));// NSLog(@"%@:%@",phoneLabel,phoneNumber);// } cell.textLabel.text=[NSString stringWithFormat:@"%@ %@",firstName,lastName]; if (count>0) { cell.detailTextLabel.text=(__bridge NSString *)(ABMultiValueCopyValueAtIndex(phoneNumbersRef, 0)); } if(ABPersonHasImageData(recordRef)){//如果有照片数据 NSData *imageData= (__bridge NSData *)(ABPersonCopyImageData(recordRef)); cell.imageView.image=[UIImage imageWithData:imageData]; }else{ cell.imageView.image=[UIImage imageNamed:@"avatar"];//没有图片使用默认头像 } //使用cell的tag存储记录id cell.tag=ABRecordGetRecordID(recordRef); return cell;}- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { ABRecordRef recordRef=(__bridge ABRecordRef )self.allPerson[indexPath.row]; [self removePersonWithRecord:recordRef];//从通讯录删除 [self.allPerson removeObjectAtIndex:indexPath.row];//从数组移除 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];//从列表删除 } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } }#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<count; ++i) { ABRecordRef recordRef=CFArrayGetValueAtIndex(recordsRef, i);//取得指定的记录 ABAddressBookRemoveRecord(self.addressBook, recordRef, NULL);//删除 } ABAddressBookSave(self.addressBook, NULL);//删除之后提交更改 CFRelease(recordsRef);}/** * 添加一条记录 * * @param firstName 名 * @param lastName 姓 * @param iPhoneName iPhone手机号 */-(void)addPersonWithFirstName:(NSString *)firstName lastName:(NSString *)lastName workNumber:(NSString *)workNumber{ //创建一条记录 ABRecordRef recordRef= ABPersonCreate(); ABRecordSetValue(recordRef, kABPersonFirstNameProperty, (__bridge CFTypeRef)(firstName), NULL);//添加名 ABRecordSetValue(recordRef, kABPersonLastNameProperty, (__bridge CFTypeRef)(lastName), NULL);//添加姓 ABMutableMultiValueRef multiValueRef =ABMultiValueCreateMutable(kABStringPropertyType);//添加设置多值属性 ABMultiValueAddValueAndLabel(multiValueRef, (__bridge CFStringRef)(workNumber), kABWorkLabel, NULL);//添加工作电话 ABRecordSetValue(recordRef, kABPersonPhoneProperty, multiValueRef, NULL); //添加记录 ABAddressBookAddRecord(self.addressBook, recordRef, NULL); //保存通讯录,提交更改 ABAddressBookSave(self.addressBook, NULL); //释放资源 CFRelease(recordRef); CFRelease(multiValueRef);}/** * 根据RecordID修改联系人信息 * * @param recordID 记录唯一ID * @param firstName 姓 * @param lastName 名 * @param homeNumber 工作电话 */-(void)modifyPersonWithRecordID:(ABRecordID)recordID firstName:(NSString *)firstName lastName:(NSString *)lastName workNumber:(NSString *)workNumber{ ABRecordRef recordRef=ABAddressBookGetPersonWithRecordID(self.addressBook,recordID); ABRecordSetValue(recordRef, kABPersonFirstNameProperty, (__bridge CFTypeRef)(firstName), NULL);//添加名 ABRecordSetValue(recordRef, kABPersonLastNameProperty, (__bridge CFTypeRef)(lastName), NULL);//添加姓 ABMutableMultiValueRef multiValueRef =ABMultiValueCreateMutable(kABStringPropertyType); ABMultiValueAddValueAndLabel(multiValueRef, (__bridge CFStringRef)(workNumber), kABWorkLabel, NULL); ABRecordSetValue(recordRef, kABPersonPhoneProperty, multiValueRef, NULL); //保存记录,提交更改 ABAddressBookSave(self.addressBook, NULL); //释放资源 CFRelease(multiValueRef);}@end新增或修改控制器视图,用于显示一个联系人的信息或者新增一个联系人:KCAddPersonViewController.h//// KCAddPersonViewController.h// AddressBook//// kABPersonFirstNameProperty// Copyright (c) 2014年 cmjstudio. All rights reserved.//#import <UIKit/UIKit.h>@protocol KCContactDelegate;@interface KCAddPersonViewController : UIViewController@property (assign,nonatomic) int recordID;//通讯录记录id,如果ID不为0则代表修改否则认为是新增@property (strong,nonatomic) NSString *firstNameText;@property (strong,nonatomic) NSString *lastNameText;@property (strong,nonatomic) NSString *workPhoneText;@property (strong,nonatomic) id<KCContactDelegate> delegate;@endKCAddPersonViewController.m//// KCAddPersonViewController.m// AddressBook//// kABPersonFirstNameProperty// Copyright (c) 2014年 cmjstudio. All rights reserved.//#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
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 通讯录
- 预览flv播放器
- json-c 读写文件
- 关于Matlab中avi视频的读取问题
- 如何用U盘制作Ubuntu 14.10启动盘
- 十五分钟气功睡觉法----午间休息的绝好办法
- 通讯录
- windows上的5种网络通信模型示例代码
- unity 2D 正交摄像机下 uGUi 比例与自适应问题
- PostgreSQL 之 Function NOTICE
- JS闭包是是什么?
- Makefile 将多个o文件链接成so文件
- LeetCode70——Climbing Stairs
- 前端开发者都应知道的 jQuery 小技巧
- Servlet