为了能够访问通讯录数据库,苹果开放了一些专门的API,iOS 6 之后应用访问通讯录,需要获得用户授权,通讯录对一个应用只授权一次,即使应用删除后重装,也不必再次授权。
导入
iOS 6
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
iOS 9
#import <Contacts/Contacts.h>
#import <ContactsUI/ContactsUI.h>
概述
AddressBook、AddressBookUI
AddressBook框架主要提供了直接访问通讯录中的记录和属性API,使用这些API,需要自己构建UI界面。
AddressBookUI框架提供了4个视图控制器和4个对应的委托协议,它们已经提供UI界面,不需要我们自己构建。
AddressBook框架常用的类
ABAddressBook 封装访问通讯录接口。Core Foundation框架中对应的类型是ABAddressBookRef。
ABPerson封装通讯录个人信息数据,是数据库的一条记录。Core Foundation框架中对应的类型是ABPersonRef。
ABGroup封装通讯录组信息数据,一个组包含了多个人的信息,一个人也可以隶属于多个组。Core Foundation框架中对应的类型是ABGroupRef。
ABRecord封装了数据库的一条记录,记录由属性组成。Core Foundation框架中对应的类型是ABRecordRef。
AddressBookUI框架中的视图控制器
ABPeoplePickerNavigationController它是从数据库中选取联系人的导航控制器,对应委托协议为ABPeoplePickerNavigationControllerDelegate。
ABPersonViewController查看并编辑单个联系人信息,对应的委托协议为ABPersonControllerDelegate。
ABNewPersonViewController创建新联系人信息,对应的委托协议为ABNewPersonViewControllerDelegate。
ABUnknownPersonViewController呈现记录部分信息,这些信息可以创建新联系人信息或添加到已经存在的联系人,对应的委托协议为ABUnknownPersonViewControllerDelegate。
注释:Core Foundation 框架(CF开头)和Foundtation框架(NS开头)紧密相关,它们为相同功能提供接口,但Foundation框架提供Object-C接口,Core Foundation框架提供C接口。它们某些类型可以互相转换。
读取联系人信息
// MyAddressBookViewController.m
// iOS-Contact
//
// Created by ZhixiaoLiao on 16/9/9.
// Copyright © 2016年 ZhixiaoLiao. All rights reserved.
//
#import "MyAddressBookViewController.h"
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
@interface MyAddressBookViewController ()<UISearchBarDelegate,UITableViewDelegate,UITableViewDataSource>
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
@property (strong, nonatomic) NSArray *listContacts;
@property (weak, nonatomic) IBOutlet UITableView *myTab;
@end
@implementation MyAddressBookViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.title = @"通讯录";
self.myTab.delegate = self;
self.myTab.dataSource = self;
self.searchBar.delegate = self;
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (granted) {
//查询所有
[self filterContentForSearchText:@""];
}
});
CFRelease(addressBook);
}
- (void)filterContentForSearchText:(NSString *)searchText
{
//如果没有授权,则退出
if (ABAddressBookGetAuthorizationStatus()!=kABAuthorizationStatusAuthorized) {
return;
}
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if ([searchText length] == 0) {
//查询所有
self.listContacts = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
}else{
//查询条件
CFStringRef cfSearchText = (CFStringRef)CFBridgingRetain(searchText);
self.listContacts = CFBridgingRelease(ABAddressBookCopyPeopleWithName(addressBook, cfSearchText));
CFRelease(cfSearchText);
}
[self.myTab reloadData];
CFRelease(addressBook);
}
//获得焦点,成为第一响应者
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
return YES;
}
//点击键盘上的搜索按钮
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[self.searchBar resignFirstResponder];
}
//点击搜索栏中的取消按钮
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
//查询所有
[self filterContentForSearchText:self.searchBar.text];
[self.searchBar resignFirstResponder];
}
//文本内容发生改变时调用
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
[self filterContentForSearchText:self.searchBar.text];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
ABRecordRef thisPerson = CFBridgingRetain(self.listContacts[indexPath.row]);
NSString *firstName = CFBridgingRelease(ABRecordCopyValue(thisPerson, kABPersonNoteProperty));
firstName = firstName != nil ?firstName:@"";
NSString *lastName = CFBridgingRelease(ABRecordCopyValue(thisPerson, kABPersonLastNamePhoneticProperty));
lastName = lastName != nil ?lastName:@"";
cell.textLabel.text = [NSString stringWithFormat:@"%@ %@",firstName,lastName];
// NSString *name = CFBridgingRelease(ABRecordCopyCompositeName(thisPerson));
// cell.textLabel.text = name;
CFRelease(thisPerson);
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.listContacts count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 44.0f;
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end