最全通讯录

来源:互联网 发布:js date函数 编辑:程序博客网 时间:2024/05/16 05:15

iOS访问通讯录开发-读取联系人信息

读取通信录中的联系人一般的过程是先查找联系人记录,然后再访问记录的属性,属性又可以分为单值属性和多值属性。通过下面例子介绍联系人的查询,以及单值属性和多值属性的访问,还有读取联系人中的图片数据。 
 
 
本案例是从iOS设备上读取通讯录中的联系人,并将其显示在一个表视图中,可以进行查询,点击联系人进入详细信息画面。访问通讯录的应用必须要做的两件事情: 
1、添加AddressBook和AddressBookUI框架 
为工程添加AddressBook.framework和AddressBookUI.framework 
 
 
2、引入头文件 
在需要访问通讯录类的头文件中引入下面头文件: 
#import <AddressBook/AddressBook.h> 
#import <AddressBookUI/AddressBookUI.h> 
查询联系人记录 
在从通信录数据库查询联系人数据是无法使用SQL语句,只能通过ABAddressBookCopyArrayOfAllPeople和ABAddressBookCopyPeopleWithName函数获得,它们的定义如下: 
[cpp]  FArrayRef ABAddressBookCopyArrayOfAllPeople (  
 
ABAddressBookRef addressBook  
 
);  
 
CFArrayRef ABAddressBookCopyPeopleWithName (  
 
ABAddressBookRef addressBook,  
 
CFStringRef name  
 
);  
CFArrayRef ABAddressBookCopyArrayOfAllPeople ( 
ABAddressBookRef addressBook 
); 
CFArrayRef ABAddressBookCopyPeopleWithName ( 
ABAddressBookRef addressBook, 
CFStringRef name 
); 
 
ABAddressBookCopyArrayOfAllPeople函数是查询所有的联系人数据。ABAddressBookCopyPeopleWithName函数是通过人名查询通讯录中的联系人,其中的name参数就是查询的前缀关键字。两个函数中都有addressBook参数,它是我们要查询的通讯录对象,其创建使用ABAddressBookCreateWithOptions函数(在iOS6之前是ABAddressBookCreate函数),它的定义: 
[cpp]  ABAddressBookRef ABAddressBookCreateWithOptions (  
 
CFDictionaryRef options,  
 
CFErrorRef* error  
 
);  
ABAddressBookRef ABAddressBookCreateWithOptions ( 
CFDictionaryRef options, 
CFErrorRef* error 
); 
 
options参数是保留参数,目前没有采用,使用时候可以传递NULL值。error是错误对象,包含错误信息。 
下面是我们代码中有关系查询的部分,先看一下ViewController.h: 
[cpp] 
#import <UIKit/UIKit.h>   
 
#import <AddressBook/AddressBook.h>   
 
#import ”DetailViewController.h”   
 
@interface ViewController : UITableViewController  
 
<UISearchBarDelegate, UISearchDisplayDelegate>  
 
@property (nonatomic, strong) NSArray *listContacts;  
 
- (void)filterContentForSearchText:(NSString*)searchText;  
 
@end  
#import <UIKit/UIKit.h> 
#import <AddressBook/AddressBook.h> 
#import ”DetailViewController.h” 
@interface ViewController : UITableViewController 
<UISearchBarDelegate, UISearchDisplayDelegate> 
@property (nonatomic, strong) NSArray *listContacts; 
- (void)filterContentForSearchText:(NSString*)searchText; 
@end 
 
属性listContacts是装载联系人记录数组集合,filterContentForSearchText:方法是用来过滤联系人信息的方法,也就是查询方法。 
ViewController.m中的viewDidLoad方法: 
[cpp] 
- (void)viewDidLoad  
 
{  
 
[super viewDidLoad];  
 
CFErrorRef error = NULL;  
 
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error); ①  
 
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { ②  
 
if (granted) {  
 
//查询所有   
 
[self filterContentForSearchText:@""];  ③  
 
}  
 
});  
 
CFRelease(addressBook);  ④  
 
}  
- (void)viewDidLoad 

[super viewDidLoad]; 
CFErrorRef error = NULL; 
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error); ① 
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) { ② 
if (granted) { 
//查询所有 
[self filterContentForSearchText:@""];  ③ 

}); 
CFRelease(addressBook);  ④ 

 
在viewDidLoad方法中首先在第①行代码处使用ABAddressBookCreateWithOptions函数创建addressBook对象,然后在第②行又调用了函数ABAddressBookRequestAccessWithCompletion,这个函数用于向用户请求访问通讯录数据库,如果是第一次访问,则会弹出一个用户授权对话框,如果用户授权可以访问则会调用下面的代码块。 
[cpp] 
^(bool granted, CFErrorRef error) {  
 
if (granted) {  
 
}  
 
});  
^(bool granted, CFErrorRef error) { 
if (granted) { 

}); 
 
由于请求和代码块的回调都是异步的,你会发现表视图画面先出现,然后过一会儿才有查询出来的结果。在iOS6之后这个请求过程必须有的,否则无法访问通讯录数据库。 
ViewController.m中的filterContentForSearchText:查询方法: 
[cpp] 
- (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.tableView reloadData];  
 
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.tableView reloadData]; 
CFRelease(addressBook); 

 
在该方法中实现查询,ABAddressBookGetAuthorizationStatus()函数返回应用的授权状态,其中kABAuthorizationStatusAuthorized常量代表用户已经授权,在没有授权情况下该方法不进行任何处理。ABAddressBookCopyArrayOfAllPeople函数是查询所有数据,ABAddressBookCopyPeopleWithName函数是根据条件查询,返回值是CFArrayRef类型,不能直接赋值给listContacts(NSArray*类型)属性,处理方式一般如下两种: 
self.listContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook) ; 
或 
self.listContacts = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook)); 
(__bridge NSArray *)方式不会转让对象所有权,只是简单强制转化。CFBridgingRelease函数实现的是Core Foundation类型到Foundation类型转化并把对象所有权转让ARC(自动管理引用计数),因此不需要释放属性listContacts对应的成员变量。类似还有CFBridgingRetain函数,实现的是Foundation类型到Core Foundation类型转化, 并把对象所有权转让调用者,因此需要释放这个对象,代码如下: 
[cpp] 
CFStringRef cfSearchText = (CFStringRef)CFBridgingRetain(searchText);  
 
self.listContacts = CFBridgingRelease(ABAddressBookCopyPeopleWithName(addressBook, cfSearchText));  
 
CFRelease(cfSearchText);  
CFStringRef cfSearchText = (CFStringRef)CFBridgingRetain(searchText); 
self.listContacts = CFBridgingRelease(ABAddressBookCopyPeopleWithName(addressBook, cfSearchText)); 
CFRelease(cfSearchText); 
 
最后在第④行调用CFRelease(addressBook)函数释放addressBook对象,Core Foundation框架中的数据类型内存管理是不受ARC管理的,但是与Foundation框架的MRC管理类似,需要手动释放,CFRelease函数就是相当于Foundation框架中的release(或autorelease)方法。 
ViewController.m中的SearchBar查询相关方法: 
#pragma mark –UISearchBarDelegate 协议方法 
[cpp] 
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar  
 
{  
 
//查询所有   
 
[self filterContentForSearchText:@""];  
 
}  
 
#pragma mark - UISearchDisplayController Delegate Methods   
 
//当文本内容发生改变时候,向表视图数据源发出重新加载消息   
 
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller  
 
shouldReloadTableForSearchString:(NSString *)searchString  
 
{  
 
[self filterContentForSearchText:searchString];  
 
//YES情况下表视图可以重新加载   
 
return YES;  
 
}  
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar 

//查询所有 
[self filterContentForSearchText:@""]; 

#pragma mark - UISearchDisplayController Delegate Methods 
//当文本内容发生改变时候,向表视图数据源发出重新加载消息 
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller 
shouldReloadTableForSearchString:(NSString *)searchString 

[self filterContentForSearchText:searchString]; 
//YES情况下表视图可以重新加载 
return YES; 

 
读取单值属性 
在一条联系人记录中,有很多属性,这些属性有单值属性和多值属性,单值属性是只有一个值的属性,如:姓氏、名字等,它们是由下面常量定义的: 
kABPersonFirstNameProperty,名字 
kABPersonLastNameProperty,姓氏 
kABPersonMiddleNameProperty,中间名 
kABPersonPrefixProperty,前缀 
kABPersonSuffixProperty,后缀 
kABPersonNicknameProperty,昵称 
kABPersonFirstNamePhoneticProperty,名字汉语拼音或音标 
kABPersonLastNamePhoneticProperty,姓氏汉语拼音或音标 
q kABPersonMiddleNamePhoneticProperty,中间名汉语拼音或音标 
kABPersonOrganizationProperty,组织名 
kABPersonJobTitleProperty,头衔 
kABPersonDepartmentProperty,部门 
kABPersonNoteProperty,备注 
读取记录属性函数是ABRecordCopyValue,ABRecordCopyValue函数的定义如下: 
[cpp] 
CFTypeRef ABRecordCopyValue (  
 
ABRecordRef record,  
 
ABPropertyID property  
 
);  
CFTypeRef ABRecordCopyValue ( 
ABRecordRef record, 
ABPropertyID property 
); 
 
ABRecordRef参数是记录对象,ABPropertyID是属性ID,就是上面的常量kABPersonFirstNameProperty等。返回值类型是CFTypeRef,它是Core Foundation类型的“泛型”,可以代表任何的Core Foundation类型。 
ViewController.m中的tableView:cellForRowAtIndexPath:方法,主要实现了访问单值属性: 
[cpp] 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath  
 
{  
 
static NSString *CellIdentifier = @”Cell”;  
 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];  
 
if (cell == nil) {  
 
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];  
 
}  
 
ABRecordRef thisPerson = CFBridgingRetain([self.listContacts objectAtIndex:[indexPath row]]); ①        NSString *firstName = CFBridgingRelease(ABRecordCopyValue(thisPerson, kABPersonFirstNameProperty)); ②  
 
firstName = firstName != nil?firstName:@”";  
 
NSString *lastName =  CFBridgingRelease(ABRecordCopyValue(thisPerson, kABPersonLastNameProperty));  ③  
 
lastName = lastName != nil?lastName:@”";  
 
cell.textLabel.text = [NSString stringWithFormat:@"%@ %@",firstName,lastName];  
 
CFRelease(thisPerson);  
 
return cell;  
 
}  
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

static NSString *CellIdentifier = @”Cell”; 
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) { 
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 

ABRecordRef thisPerson = CFBridgingRetain([self.listContacts objectAtIndex:[indexPath row]]); ①        NSString *firstName = CFBridgingRelease(ABRecordCopyValue(thisPerson, kABPersonFirstNameProperty)); ② 
firstName = firstName != nil?firstName:@”"; 
NSString *lastName =  CFBridgingRelease(ABRecordCopyValue(thisPerson, kABPersonLastNameProperty));  ③ 
lastName = lastName != nil?lastName:@”"; 
cell.textLabel.text = [NSString stringWithFormat:@"%@ %@",firstName,lastName]; 
CFRelease(thisPerson); 
return cell; 

 
第①行ABRecordRef thisPerson = CFBridgingRetain([self.listContacts objectAtIndex:[indexPath row]])语句是从NSArray*集合中取出一个元素,并且转化为Core Foundation类型的ABRecordRef类型。CFBridgingRelease(ABRecordCopyValue(thisPerson, kABPersonFirstNameProperty))语句是将名字属性取出来,转化为NSString*类型。最后CFRelease(thisPerson)是释放ABRecordRef对象。 
此外,为了把选中的联系人传递给详细画面,我们需要获得选中记录的ID,然后把ID传递到详细画面,这个过程处理是在ViewController.m中的 prepareForSegue:方法完成的: 
[cpp] 
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender  
 
{  
 
if ([[segue identifier] isEqualToString:@”showDetail”]) {  
 
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];  
 
ABRecordRef thisPerson = CFBridgingRetain([self.listContacts objectAtIndex:[indexPath row]]);  
 
DetailViewController *detailViewController = [segue destinationViewController];  
 
ABRecordID personID = ABRecordGetRecordID(thisPerson); ①  
 
NSNumber *personIDAsNumber = [NSNumber numberWithInt:personID];  ②  
 
detailViewController.personIDAsNumber = personIDAsNumber;  ③  
 
CFRelease(thisPerson);  ④  
 
}  
 
}  
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 

if ([[segue identifier] isEqualToString:@”showDetail”]) { 
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 
ABRecordRef thisPerson = CFBridgingRetain([self.listContacts objectAtIndex:[indexPath row]]); 
DetailViewController *detailViewController = [segue destinationViewController]; 
ABRecordID personID = ABRecordGetRecordID(thisPerson); ① 
NSNumber *personIDAsNumber = [NSNumber numberWithInt:personID];  ② 
detailViewController.personIDAsNumber = personIDAsNumber;  ③ 
CFRelease(thisPerson);  ④ 


 
其中第①行代码调用函数ABRecordGetRecordID是获取选中记录的ID,其中ID为ABRecordID类型。为了传递这个ID给DetailViewController视图控制器,DetailViewController视图控制器定义了personIDAsNumber属性,在第③行将ID给personIDAsNumber属性。DetailViewController.h代码如下: 
#import <UIKit/UIKit.h> 
#import <AddressBook/AddressBook.h> 
@interface DetailViewController : UITableViewController 
@property (weak, nonatomic) IBOutlet UIImageView *imageView; 
@property (weak, nonatomic) IBOutlet UILabel *lblName; 
@property (weak, nonatomic) IBOutlet UILabel *lblMobile; 
@property (weak, nonatomic) IBOutlet UILabel *lblIPhone; 
@property (weak, nonatomic) IBOutlet UILabel *lblWorkEmail; 
@property (weak, nonatomic) IBOutlet UILabel *lblHomeEmail; 
@property (strong, nonatomic) NSNumber* personIDAsNumber; 
@end 
personIDAsNumber属性为NSNumber*类型。 
读取多值属性 
多值属性是包含多个值的集合类型,如:电话号码、Email、URL等,它们主要是由下面常量定义的: 
kABPersonPhoneProperty,电话号码属性,kABMultiStringPropertyType类型多值属性; 
kABPersonEmailProperty,Email属性,kABMultiStringPropertyType类型多值属性; 
kABPersonURLProperty,URL属性,kABMultiStringPropertyType类型多值属性; 
kABPersonRelatedNamesProperty,亲属关系人属性,kABMultiStringPropertyType类型多值属性; 
kABPersonAddressProperty,地址属性,kABMultiDictionaryPropertyType类型多值属性; 
kABPersonInstantMessageProperty,即时聊天属性,kABMultiDictionaryPropertyType类型多值属性; 
kABPersonSocialProfileProperty,社交账号属性,kABMultiDictionaryPropertyType类型多值属性; 
在多值属性中包含了label(标签)、value(值)和ID等部分,其中标签和值都是可以重复的,而ID是不能重复的 
 
多值属性访问方式与单值属性访问类似都使用ABRecordCopyValue函数。不同的是多值属性访问返回值是ABMultiValueRef,然后要使用ABMultiValueCopyArrayOfAllValues函数从ABMultiValueRef对象中获取数组CFArrayRef集合。ABMultiValueCopyArrayOfAllValues函数的定义如下: 
[cpp] 
CFArrayRef ABMultiValueCopyArrayOfAllValues (  
 
ABMultiValueRef multiValue  
 
);  
 
ABMultiValueCopyLabelAtIndex函数可以从ABMultiValueRef对象中返回标签,其定义如下:  
 
CFStringRef ABMultiValueCopyLabelAtIndex (  
 
ABMultiValueRef multiValue,  
 
CFIndex index  
 
);  
CFArrayRef ABMultiValueCopyArrayOfAllValues ( 
ABMultiValueRef multiValue 
); 
ABMultiValueCopyLabelAtIndex函数可以从ABMultiValueRef对象中返回标签,其定义如下: 
CFStringRef ABMultiValueCopyLabelAtIndex ( 
ABMultiValueRef multiValue, 
CFIndex index 
); 
 
参数multiValue是ABMultiValueRef对象,index是查找标签的索引。 
ABMultiValueGetIdentifierAtIndex函数可以从ABMultiValueRef对象中返回ID,其定义如下: 
[cpp] 
ABMultiValueIdentifier ABMultiValueGetIdentifierAtIndex (  
 
ABMultiValueRef multiValue,  
 
CFIndex index  
 
);  
 
在DetailViewController.m文件viewDidLoad方法中取得Email多值属性,其代码如下:  
 
ABMultiValueRef emailsProperty = ABRecordCopyValue(person, kABPersonEmailProperty);  
 
NSArray* emailsArray = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(emailsProperty));  
 
for(int index = 0; index< [emailsArray count]; index++){  
 
NSString *email = [emailsArray objectAtIndex:index];  
 
NSString *emailLabel = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(emailsProperty, index));  
 
if ([emailLabel isEqualToString:(NSString*)kABWorkLabel]) {  
 
[self.lblWorkEmail setText:email];  
 
} else if ([emailLabel isEqualToString:(NSString*)kABHomeLabel]) {  
 
[self.lblHomeEmail setText:email];  
 
} else {  
 
NSLog(@”%@: %@”, @”其它Email”, email);  
 
}  
 
}  
 
CFRelease(emailsProperty);  
ABMultiValueIdentifier ABMultiValueGetIdentifierAtIndex ( 
ABMultiValueRef multiValue, 
CFIndex index 
); 
在DetailViewController.m文件viewDidLoad方法中取得Email多值属性,其代码如下: 
ABMultiValueRef emailsProperty = ABRecordCopyValue(person, kABPersonEmailProperty); 
NSArray* emailsArray = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(emailsProperty)); 
for(int index = 0; index< [emailsArray count]; index++){ 
NSString *email = [emailsArray objectAtIndex:index]; 
NSString *emailLabel = CFBridgingRelease(ABMultiValueCopyLabelAtIndex(emailsProperty, index)); 
if ([emailLabel isEqualToString:(NSString*)kABWorkLabel]) { 
[self.lblWorkEmail setText:email]; 
} else if ([emailLabel isEqualToString:(NSString*)kABHomeLabel]) { 
[self.lblHomeEmail setText:email]; 
} else { 
NSLog(@”%@: %@”, @”其它Email”, email); 


CFRelease(emailsProperty); 
 
其中ABMultiValueCopyArrayOfAllValues(emailsProperty))语句是从emailsProperty属性中取出数组集合。kABWorkLabel和kABHomeLabel都是Email多值属性的标签。kABWorkLabel是工作Email标签和kABHomeLabel是家庭Email标签,另外还有kABOtherLabel,它是Email标签。最后emailsProperty需要释放。 
DetailViewController.m中的viewDidLoad方法中取得电话号码多值属性代码如下: 
[cpp] 
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);  
 
NSArray* phoneNumberArray = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(phoneNumberProperty));  
 
for(int index = 0; index< [phoneNumberArray count]; index++){  
 
NSString *phoneNumber = [phoneNumberArray objectAtIndex:index];  
 
NSString *phoneNumberLabel =  
 
CFBridgingRelease(ABMultiValueCopyLabelAtIndex(phoneNumberProperty, index));  
 
if ([phoneNumberLabel isEqualToString:(NSString*)kABPersonPhoneMobileLabel]) {  
 
[self.lblMobile setText:phoneNumber];  
 
} else if ([phoneNumberLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel]) {  
 
[self.lblIPhone setText:phoneNumber];  
 
} else {  
 
NSLog(@”%@: %@”, @”其它电话”, phoneNumber);  
 
}  
 
}  
 
CFRelease(phoneNumberProperty);  
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(person, kABPersonPhoneProperty); 
NSArray* phoneNumberArray = CFBridgingRelease(ABMultiValueCopyArrayOfAllValues(phoneNumberProperty)); 
for(int index = 0; index< [phoneNumberArray count]; index++){ 
NSString *phoneNumber = [phoneNumberArray objectAtIndex:index]; 
NSString *phoneNumberLabel = 
CFBridgingRelease(ABMultiValueCopyLabelAtIndex(phoneNumberProperty, index)); 
if ([phoneNumberLabel isEqualToString:(NSString*)kABPersonPhoneMobileLabel]) { 
[self.lblMobile setText:phoneNumber]; 
} else if ([phoneNumberLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel]) { 
[self.lblIPhone setText:phoneNumber]; 
} else { 
NSLog(@”%@: %@”, @”其它电话”, phoneNumber); 


CFRelease(phoneNumberProperty); 
 
kABPersonPhoneMobileLabel和kABPersonPhoneIPhoneLabel都是电话号码属性的标签。kABPersonPhoneMobileLabel是移动电话号码标签,kABPersonPhoneIPhoneLabel是iPhone电话号码标签。此外还有: 
kABPersonPhoneMainLabel,主要电话号码标签; 
kABPersonPhoneHomeFAXLabel,家庭传真电话号码标签; 
kABPersonPhoneWorkFAXLabel,工作传真电话号码标签; 
kABPersonPhonePagerLabel,寻呼机号码标签。 
读取图片属性 
通讯录中的联系人可以有一个图片,读取联系人图片的相关函数有ABPersonCopyImageData和ABPersonHasImageData等。ABPersonCopyImageData可以读取联系人图片函数,它的定义如下: 
[cpp] 
CFDataRef ABPersonCopyImageData (  
 
ABRecordRef person  
 
);  
CFDataRef ABPersonCopyImageData ( 
ABRecordRef person 
); 
 
它的返回类型是CFDataRef,与之对应的Foundation框架类型是NSData*。ABPersonHasImageData函数用于判断联系人是否有图片,它的定义如下: 
[cpp] 
bool ABPersonHasImageData (  
 
ABRecordRef person  
 
);  
 
DetailViewController.m中的viewDidLoad方法中取得联系人图片代码如下:  
 
if (ABPersonHasImageData(person)) {  
 
NSData *photoData = CFBridgingRelease(ABPersonCopyImageData(person));  
 
if(photoData){  
 
[self.imageView setImage:[UIImage imageWithData:photoData]];  
 
}  
 
}  
bool ABPersonHasImageData ( 
ABRecordRef person 
); 
DetailViewController.m中的viewDidLoad方法中取得联系人图片代码如下: 
if (ABPersonHasImageData(person)) { 
NSData *photoData = CFBridgingRelease(ABPersonCopyImageData(person)); 
if(photoData){ 
[self.imageView setImage:[UIImage imageWithData:photoData]]; 


 
ABPersonCopyImageData取出的是CFDataRef类型,将其转化为NSData*,再使用UIImage的构造方法imageWithData:构建UIImage对象,然后再把UIImage对象赋值给imageView图片控件。
taonavy2013-07-19 14:04//---------------------------------------------------// 
//向通讯录添加新纪录(名字。号码) 
- (void)addNewPhoneNumberWith:(NSString*)firstName withLastName:(NSString*)lastName withNumber:(NSString*)phoneNumber 

    // 初始化一个ABAddressBookRef对象,使用完之后需要进行释放, 
    // 这里使用CFRelease进行释放 
    // 相当于通讯录的一个引用 
    ABAddressBookRef addressBook = ABAddressBookCreate(); 
    CFErrorRef error = NULL; 
    // 新建一个联系人 
    // ABRecordRef是一个属性的集合,相当于通讯录中联系人的对象 
    // 联系人对象的属性分为两种: 
    // 只拥有唯一值的属性和多值的属性。 
    // 唯一值的属性包括:姓氏、名字、生日等。 
    // 多值的属性包括:电话号码、邮箱等。 
    ABRecordRef person = ABPersonCreate(); 
    NSDate *birthday = [NSDate date]; 
//    // 电话号码数组 
//    NSArray *phones = [NSArray arrayWithObjects:@"123",@"456", nil]; 
//    // 电话号码对应的名称 
//    NSArray *labels = [NSArray arrayWithObjects:@"iphone",@"home", nil]; 
    // 保存到联系人对象中,每个属性都对应一个宏,例如:kABPersonFirstNameProperty 
    // 设置firstName属性 
    ABRecordSetValue(person, kABPersonFirstNameProperty, (CFStringRef)firstName, NULL); 
    // 设置lastName属性 
    ABRecordSetValue(person, kABPersonLastNameProperty, (CFStringRef) lastName, NULL); 
    // 设置birthday属性 
    ABRecordSetValue(person, kABPersonBirthdayProperty, (CFDateRef)birthday, NULL); 
    // ABMultiValueRef类似是Objective-C中的NSMutableDictionary 
    //phone number 
    ABMutableMultiValueRef multiPhone = ABMultiValueCreateMutable(kABMultiStringPropertyType); 
    ABMultiValueAddValueAndLabel(multiPhone, [self creatArandStringWith:1], kABPersonPhoneMainLabel, NULL); 
    ABRecordSetValue(person, kABPersonPhoneProperty, multiPhone,&error); 
    CFRelease(multiPhone); 
    // 将新建的联系人添加到通讯录中 
    ABAddressBookAddRecord(addressBook, person, NULL); 
    // 保存通讯录数据 
    ABAddressBookSave(addressBook, NULL); 
    // 释放通讯录对象的引用 
    if (addressBook) { 
        CFRelease(addressBook); 
    } 

  
  
//----------------------------------------------------// 
//随即添加通讯录,指添加name,和phone number 
  
-(NSString*)sigleCwithType:(int)type 

    if (type) { 
        srand((unsigned)time(0)); 
        int num = rand(); 
        return [NSString stringWithFormat:@"%d",num]; 
    }else{ 
        srand((unsigned)time(0)); 
        int num = rand()%26; 
        return [NSString stringWithFormat:@"%c",'a'+num]; 
    } 

  
-(NSString*)creatArandStringWith:(int)type 

    srand((unsigned)time(0)); 
    int num = rand(); 
    NSMutableString* str = [NSMutableString string]; 
    for (int i = 0; i < num;  i++) { 
        [str appendString:[self sigleCwithType:type]]; 
    } 
    return str; 

  
  
-(void)addToContactWith:(int)index 

    printf("--------addToContact----Execute!!!------n"); 
      
    ABAddressBookRef iPhoneAddressBook = ABAddressBookCreate(); 
    ABRecordRef newPerson = ABPersonCreate(); 
    CFErrorRef error = NULL; 
    ABRecordSetValue(newPerson, kABPersonFirstNameProperty, [self creatArandStringWith:0], &error); 
    ABRecordSetValue(newPerson, kABPersonLastNameProperty, [self creatArandStringWith:0], &error); 
      
    //phone number 
    ABMutableMultiValueRef multiPhone = ABMultiValueCreateMutable(kABMultiStringPropertyType); 
    ABMultiValueAddValueAndLabel(multiPhone, [self creatArandStringWith:1], kABPersonPhoneMainLabel, NULL); 
    ABRecordSetValue(newPerson, kABPersonPhoneProperty, multiPhone,&error); 
    CFRelease(multiPhone); 
      
    //email 
    ABMutableMultiValueRef multiEmail = ABMultiValueCreateMutable(kABMultiStringPropertyType); 
    ABMultiValueAddValueAndLabel(multiEmail, @"johndoe@modelmetrics.com", kABWorkLabel, NULL); 
    ABRecordSetValue(newPerson, kABPersonEmailProperty, multiEmail, &error); 
    CFRelease(multiEmail); 
    ABAddressBookAddRecord(iPhoneAddressBook, newPerson, &error); 
    ABAddressBookSave(iPhoneAddressBook, &error); 
    if (error != NULL) 
    { 
        NSLog(@"Danger Will Robinson! Danger!"); 
    } 

  
//----------------------------------------------------// 
删除电话本 
- (void)deletePhoneNumber 

    // 初始化并创建通讯录对象,记得释放内存 
    ABAddressBookRef addressBook = ABAddressBookCreate(); 
    // 获取通讯录中所有的联系人 
    NSArray *array = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 
    // 遍历所有的联系人并删除(这里只删除姓名为张三的) 
    for (id obj in array) { 
       ABRecordRef people = (ABRecordRef)obj; 
       ABAddressBookRemoveRecord(addressBook, people, NULL); 
    } 
    // 保存修改的通讯录对象 
    ABAddressBookSave(addressBook, NULL); 
    // 释放通讯录对象的内存 
    if (addressBook) { 
        CFRelease(addressBook); 
    } 

//--------------修改电话本内容-----------------------// 
  
+ (void) updateAddressBookPersonWithFirstName:(NSString *)firstName 
                                     lastName:(NSString *)lastName 
                                       mobile:(NSString *)mobile 
                                     nickname:(NSString *)nickname 
                                     birthday:(NSDate *)birthday { 
      
    // 初始化并创建通讯录对象,记得释放内存 
    ABAddressBookRef addressBook = ABAddressBookCreate(); 
    // 获取通讯录中所有的联系人 
    NSArray *array = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 
    // 遍历所有的联系人并修改指定的联系人 
    for (id obj in array) { 
        ABRecordRef people = (ABRecordRef)obj; 
        NSString *fn = (NSString *)ABRecordCopyValue(people, kABPersonFirstNameProperty); 
        NSString *ln = (NSString *)ABRecordCopyValue(people, kABPersonLastNameProperty); 
        ABMultiValueRef mv = ABRecordCopyValue(people, kABPersonPhoneProperty); 
        NSArray *phones = (NSArray *)ABMultiValueCopyArrayOfAllValues(mv); 
        // firstName同时为空或者firstName相等 
        BOOL ff = ([fn length] == 0 && [firstName length] == 0) || ([fn isEqualToString:firstName]); 
        // lastName同时为空或者lastName相等 
        BOOL lf = ([ln length] == 0 && [lastName length] == 0) || ([ln isEqualToString:lastName]); 
        // 由于获得到的电话号码不符合标准,所以要先将其格式化再比较是否存在 
        BOOL is = NO; 
        for (NSString *p in phones) { 
            // 红色代码处,我添加了一个类别(给NSString扩展了一个方法),该类别的这个方法主要是用于将电话号码中的"("、")"、" "、"-"过滤掉 
//            if ([[p iPhoneStandardFormat] isEqualToString:mobile]) { 
//                is = YES; 
//                break; 
//            } 
        } 
        // firstName、lastName、mobile 同时存在进行修改 
        if (ff && lf && is) { 
            if ([nickname length] > 0) { 
                ABRecordSetValue(people, kABPersonNicknameProperty, (CFStringRef)nickname, NULL); 
                } 
            if (birthday != nil) { 
                ABRecordSetValue(people, kABPersonBirthdayProperty, (CFDataRef)birthday, NULL); 
            } 
        } 
    } 
    // 保存修改的通讯录对象 
    ABAddressBookSave(addressBook, NULL); 
    // 释放通讯录对象的内存 
    if (addressBook) { 
        CFRelease(addressBook); 
    } 

//--------------------------------------------------------// 
//电话本的读取 
-(void)ReadPhoneBook 

    ABAddressBookRef addressBook = nil; 
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0){//ios6.0 
        addressBook = ABAddressBookCreateWithOptions(NULL, NULL); 
        dispatch_semaphore_t sema = dispatch_semaphore_create(0); 
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error){dispatch_semaphore_signal(sema);}); 
        dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 
        dispatch_release(sema); 
    } else { 
        addressBook = ABAddressBookCreate(); 
    } 
    NSArray *tmpPeoples = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 
    for(id tmpPerson in tmpPeoples) 
    { 
        NSMutableDictionary* dic = [[NSMutableDictionary alloc]initWithCapacity:2]; 
        //获取的联系人单一属性:First name 
        NSString* tmpFirstName = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonFirstNameProperty); 
        NSLog(@"First name:%@", tmpFirstName); 
        [tmpFirstName release]; 
        //获取的联系人单一属性:Last name 
        NSString* tmpLastName = (NSString*)ABRecordCopyValue(tmpPerson, kABPersonLastNameProperty); 
        NSLog(@"Last name:%@", tmpLastName); 
        [tmpLastName release]; 
  
        //获取的联系人单一属性:Generic phone number 
        ABMultiValueRef tmpPhones = ABRecordCopyValue(tmpPerson, kABPersonPhoneProperty); 
        NSMutableArray* numbers =[[NSMutableArray alloc] initWithCapacity:3]; 
        for(NSInteger j = 0; j < ABMultiValueGetCount(tmpPhones); j++) 
        { 
            NSString* tmpPhoneIndex = (NSString*)ABMultiValueCopyValueAtIndex(tmpPhones, j); 
            [numbers addObject:tmpPhoneIndex]; 
            NSLog(@"tmpPhoneIndex%d:%@", j, tmpPhoneIndex); 
            [tmpPhoneIndex release]; 
        } 
        [dic setObject:[self userNameWithFirst:tmpFirstName withLast:tmpLastName] forKey:@"peopleName"]; 
        NSLog(@"%@",[dic objectForKey:@"peopleName"]); 
        [dic setObject: [self phoneNumber:[self phoneNumWith:numbers]] forKey:@"phoneNum"]; 
        if ([numbers count] > 0) { 
            [phoneBook addObject:dic]; 
        } 
        [dic release]; 
        [numbers release]; 
        CFRelease(tmpPhones); 
    } 
    //释放内存 
    [tmpPeoples release]; 
    if (addressBook != nil) { 
        CFRelease(addressBook); 
    } 
      
}
0 0