iOS訪問通訊錄開發(fā)-讀取聯(lián)系人信息

讀取通信錄中的聯(lián)系人一般的過程是先查找聯(lián)系人記錄,然后再訪問記錄的屬性,屬性又可以分為單值屬性和多值屬性。通過下面例子介紹聯(lián)系人的查詢,以及單值屬性和多值屬性的訪問,還有讀取聯(lián)系人中的圖片數(shù)據(jù)。

目前創(chuàng)新互聯(lián)已為千余家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、綿陽服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計、延安網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

iOS訪問通訊錄開發(fā)-讀取聯(lián)系人信息

本案例是從iOS設(shè)備上讀取通訊錄中的聯(lián)系人,并將其顯示在一個表視圖中,可以進行查詢,點擊聯(lián)系人進入詳細信息畫面。訪問通訊錄的應(yīng)用必須要做的兩件事情:

1、添加AddressBook和AddressBookUI框架

為工程添加AddressBook.framework和AddressBookUI.framework

iOS訪問通訊錄開發(fā)-讀取聯(lián)系人信息

2、引入頭文件

在需要訪問通訊錄類的頭文件中引入下面頭文件:

#import <AddressBook/AddressBook.h>

#import <AddressBookUI/AddressBookUI.h>

查詢聯(lián)系人記錄

在從通信錄數(shù)據(jù)庫查詢聯(lián)系人數(shù)據(jù)是無法使用SQL語句,只能通過ABAddressBookCopyArrayOfAllPeople和ABAddressBookCopyPeopleWithName函數(shù)獲得,它們的定義如下:

CFArrayRef ABAddressBookCopyArrayOfAllPeople (
ABAddressBookRef addressBook
);
CFArrayRef ABAddressBookCopyPeopleWithName (
ABAddressBookRef addressBook,
CFStringRef name
);

ABAddressBookCopyArrayOfAllPeople函數(shù)是查詢所有的聯(lián)系人數(shù)據(jù)。ABAddressBookCopyPeopleWithName函數(shù)是通過人名查詢通訊錄中的聯(lián)系人,其中的name參數(shù)就是查詢的前綴關(guān)鍵字。兩個函數(shù)中都有addressBook參數(shù),它是我們要查詢的通訊錄對象,其創(chuàng)建使用ABAddressBookCreateWithOptions函數(shù)(在iOS6之前是ABAddressBookCreate函數(shù)),它的定義:

ABAddressBookRef ABAddressBookCreateWithOptions (
CFDictionaryRef options,
CFErrorRef* error
);

options參數(shù)是保留參數(shù),目前沒有采用,使用時候可以傳遞NULL值。error是錯誤對象,包含錯誤信息。

下面是我們代碼中有關(guān)系查詢的部分,先看一下ViewController.h:

#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是裝載聯(lián)系人記錄數(shù)組集合,filterContentForSearchText:方法是用來過濾聯(lián)系人信息的方法,也就是查詢方法。

ViewController.m中的viewDidLoad方法:

- (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函數(shù)創(chuàng)建addressBook對象,然后在第②行又調(diào)用了函數(shù)ABAddressBookRequestAccessWithCompletion,這個函數(shù)用于向用戶請求訪問通訊錄數(shù)據(jù)庫,如果是第一次訪問,則會彈出一個用戶授權(quán)對話框,如果用戶授權(quán)可以訪問則會調(diào)用下面的代碼塊。

^(bool granted, CFErrorRef error) {
if (granted) {
}
});

由于請求和代碼塊的回調(diào)都是異步的,你會發(fā)現(xiàn)表視圖畫面先出現(xiàn),然后過一會兒才有查詢出來的結(jié)果。在iOS6之后這個請求過程必須有的,否則無法訪問通訊錄數(shù)據(jù)庫。

ViewController.m中的filterContentForSearchText:查詢方法:

- (void)filterContentForSearchText:(NSString*)searchText
{
//如果沒有授權(quán)則退出
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);
}

在該方法中實現(xiàn)查詢,ABAddressBookGetAuthorizationStatus()函數(shù)返回應(yīng)用的授權(quán)狀態(tài),其中kABAuthorizationStatusAuthorized常量代表用戶已經(jīng)授權(quán),在沒有授權(quán)情況下該方法不進行任何處理。ABAddressBookCopyArrayOfAllPeople函數(shù)是查詢所有數(shù)據(jù),ABAddressBookCopyPeopleWithName函數(shù)是根據(jù)條件查詢,返回值是CFArrayRef類型,不能直接賦值給listContacts(NSArray*類型)屬性,處理方式一般如下兩種:

self.listContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook) ;

self.listContacts = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));

(__bridge NSArray *)方式不會轉(zhuǎn)讓對象所有權(quán),只是簡單強制轉(zhuǎn)化。CFBridgingRelease函數(shù)實現(xiàn)的是Core Foundation類型到Foundation類型轉(zhuǎn)化并把對象所有權(quán)轉(zhuǎn)讓ARC(自動管理引用計數(shù)),因此不需要釋放屬性listContacts對應(yīng)的成員變量。類似還有CFBridgingRetain函數(shù),實現(xiàn)的是Foundation類型到Core Foundation類型轉(zhuǎn)化, 并把對象所有權(quán)轉(zhuǎn)讓調(diào)用者,因此需要釋放這個對象,代碼如下:

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);

最后在第④行調(diào)用CFRelease(addressBook)函數(shù)釋放addressBook對象,Core Foundation框架中的數(shù)據(jù)類型內(nèi)存管理是不受ARC管理的,但是與Foundation框架的MRC管理類似,需要手動釋放,CFRelease函數(shù)就是相當于Foundation框架中的release(或autorelease)方法。

ViewController.m中的SearchBar查詢相關(guān)方法:

#pragma mark –UISearchBarDelegate 協(xié)議方法

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
//查詢所有
[self filterContentForSearchText:@""];
}
#pragma mark - UISearchDisplayController Delegate Methods
//當文本內(nèi)容發(fā)生改變時候,向表視圖數(shù)據(jù)源發(fā)出重新加載消息
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString];
//YES情況下表視圖可以重新加載
return YES;
}

讀取單值屬性

在一條聯(lián)系人記錄中,有很多屬性,這些屬性有單值屬性和多值屬性,單值屬性是只有一個值的屬性,如:姓氏、名字等,它們是由下面常量定義的:

kABPersonFirstNameProperty,名字

kABPersonLastNameProperty,姓氏

kABPersonMiddleNameProperty,中間名

kABPersonPrefixProperty,前綴

kABPersonSuffixProperty,后綴

kABPersonNicknameProperty,昵稱

kABPersonFirstNamePhoneticProperty,名字漢語拼音或音標

kABPersonLastNamePhoneticProperty,姓氏漢語拼音或音標

q kABPersonMiddleNamePhoneticProperty,中間名漢語拼音或音標

kABPersonOrganizationProperty,組織名

kABPersonJobTitleProperty,頭銜

kABPersonDepartmentProperty,部門

kABPersonNoteProperty,備注

讀取記錄屬性函數(shù)是ABRecordCopyValue,ABRecordCopyValue函數(shù)的定義如下:

CFTypeRef ABRecordCopyValue (

ABRecordRef record,

ABPropertyID property

);

ABRecordRef參數(shù)是記錄對象,ABPropertyID是屬性ID,就是上面的常量kABPersonFirstNameProperty等。返回值類型是CFTypeRef,它是Core Foundation類型的“泛型”,可以代表任何的Core Foundation類型。

ViewController.m中的tableView:cellForRowAtIndexPath:方法,主要實現(xiàn)了訪問單值屬性:

- (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*集合中取出一個元素,并且轉(zhuǎn)化為Core Foundation類型的ABRecordRef類型。CFBridgingRelease(ABRecordCopyValue(thisPerson, kABPersonFirstNameProperty))語句是將名字屬性取出來,轉(zhuǎn)化為NSString*類型。最后CFRelease(thisPerson)是釋放ABRecordRef對象。

此外,為了把選中的聯(lián)系人傳遞給詳細畫面,我們需要獲得選中記錄的ID,然后把ID傳遞到詳細畫面,這個過程處理是在ViewController.m中的 prepareForSegue:方法完成的:

- (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);  ④
}
}

其中第①行代碼調(diào)用函數(shù)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 *p_w_picpathView;

@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,親屬關(guān)系人屬性,kABMultiStringPropertyType類型多值屬性;

kABPersonAddressProperty,地址屬性,kABMultiDictionaryPropertyType類型多值屬性;

kABPersonInstantMessageProperty,即時聊天屬性,kABMultiDictionaryPropertyType類型多值屬性;

kABPersonSocialProfileProperty,社交賬號屬性,kABMultiDictionaryPropertyType類型多值屬性;

在多值屬性中包含了label(標簽)、value(值)和ID等部分,其中標簽和值都是可以重復(fù)的,而ID是不能重復(fù)的

iOS訪問通訊錄開發(fā)-讀取聯(lián)系人信息

多值屬性訪問方式與單值屬性訪問類似都使用ABRecordCopyValue函數(shù)。不同的是多值屬性訪問返回值是ABMultiValueRef,然后要使用ABMultiValueCopyArrayOfAllValues函數(shù)從ABMultiValueRef對象中獲取數(shù)組CFArrayRef集合。ABMultiValueCopyArrayOfAllValues函數(shù)的定義如下:

CFArrayRef ABMultiValueCopyArrayOfAllValues (
ABMultiValueRef multiValue
);
ABMultiValueCopyLabelAtIndex函數(shù)可以從ABMultiValueRef對象中返回標簽,其定義如下:
CFStringRef ABMultiValueCopyLabelAtIndex (
ABMultiValueRef multiValue,
CFIndex index
);
參數(shù)multiValue是ABMultiValueRef對象,index是查找標簽的索引。
ABMultiValueGetIdentifierAtIndex函數(shù)可以從ABMultiValueRef對象中返回ID,其定義如下:
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屬性中取出數(shù)組集合。kABWorkLabel和kABHomeLabel都是Email多值屬性的標簽。kABWorkLabel是工作Email標簽和kABHomeLabel是家庭Email標簽,另外還有kABOtherLabel,它是Email標簽。最后emailsProperty需要釋放。

DetailViewController.m中的viewDidLoad方法中取得電話號碼多值屬性代碼如下:

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,尋呼機號碼標簽。

11.2.4 讀取圖片屬性

通訊錄中的聯(lián)系人可以有一個圖片,讀取聯(lián)系人圖片的相關(guān)函數(shù)有ABPersonCopyImageData和ABPersonHasImageData等。ABPersonCopyImageData可以讀取聯(lián)系人圖片函數(shù),它的定義如下:

CFDataRef ABPersonCopyImageData (

ABRecordRef person

);

它的返回類型是CFDataRef,與之對應(yīng)的Foundation框架類型是NSData*。ABPersonHasImageData函數(shù)用于判斷聯(lián)系人是否有圖片,它的定義如下:

bool ABPersonHasImageData (
ABRecordRef person
);

DetailViewController.m中的viewDidLoad方法中取得聯(lián)系人圖片代碼如下:

if (ABPersonHasImageData(person)) {

NSData *photoData = CFBridgingRelease(ABPersonCopyImageData(person));
if(photoData){
[self.p_w_picpathView setImage:[UIImage p_w_picpathWithData:photoData]];
}
}

ABPersonCopyImageData取出的是CFDataRef類型,將其轉(zhuǎn)化為NSData*,再使用UIImage的構(gòu)造方法p_w_picpathWithData:構(gòu)建UIImage對象,然后再把UIImage對象賦值給p_w_picpathView圖片控件。

本文題目:iOS訪問通訊錄開發(fā)-讀取聯(lián)系人信息
當前鏈接:http://bm7419.com/article24/jjscce.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機網(wǎng)站導(dǎo)航、企業(yè)網(wǎng)站制作面包屑導(dǎo)航、微信公眾號、商城網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化