天天看點

iOS通路通訊錄開發-讀取聯系人資訊

讀取通信錄中的聯系人一般的過程是先查找聯系人記錄,然後再通路記錄的屬性,屬性又可以分為單值屬性和多值屬性。通過下面例子介紹聯系人的查詢,以及單值屬性和多值屬性的通路,還有讀取聯系人中的圖檔資料。

iOS通路通訊錄開發-讀取聯系人資訊

本案例是從ios裝置上讀取通訊錄中的聯系人,并将其顯示在一個表視圖中,可以進行查詢,點選聯系人進入詳細資訊畫面。通路通訊錄的應用必須要做的兩件事情:

1、添加addressbook和addressbookui架構

為工程添加addressbook.framework和addressbookui.framework

iOS通路通訊錄開發-讀取聯系人資訊

2、引入頭檔案

在需要通路通訊錄類的頭檔案中引入下面頭檔案:

#import <addressbook/addressbook.h>

#import <addressbookui/addressbookui.h>

在從通信錄資料庫查詢聯系人資料是無法使用sql語句,隻能通過abaddressbookcopyarrayofallpeople和abaddressbookcopypeoplewithname函數獲得,它們的定義如下:

abaddressbookcopyarrayofallpeople函數是查詢所有的聯系人資料。abaddressbookcopypeoplewithname函數是通過人名查詢通訊錄中的聯系人,其中的name參數就是查詢的字首關鍵字。兩個函數中都有addressbook參數,它是我們要查詢的通訊錄對象,其建立使用abaddressbookcreatewithoptions函數(在ios6之前是abaddressbookcreate函數),它的定義:

options參數是保留參數,目前沒有采用,使用時候可以傳遞null值。error是錯誤對象,包含錯誤資訊。

下面是我們代碼中有關系查詢的部分,先看一下viewcontroller.h:

屬性listcontacts是裝載聯系人記錄數組集合,filtercontentforsearchtext:方法是用來過濾聯系人資訊的方法,也就是查詢方法。

viewcontroller.m中的viewdidload方法:

在viewdidload方法中首先在第①行代碼處使用abaddressbookcreatewithoptions函數建立addressbook對象,然後在第②行又調用了函數abaddressbookrequestaccesswithcompletion,這個函數用于向使用者請求通路通訊錄資料庫,如果是第一次通路,則會彈出一個使用者授權對話框,如果使用者授權可以通路則會調用下面的代碼塊。

由于請求和代碼塊的回調都是異步的,你會發現表視圖畫面先出現,然後過一會兒才有查詢出來的結果。在ios6之後這個請求過程必須有的,否則無法通路通訊錄資料庫。

viewcontroller.m中的filtercontentforsearchtext:查詢方法:

在該方法中實作查詢,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類型轉化, 并把對象所有權轉讓調用者,是以需要釋放這個對象,代碼如下:

最後在第④行調用cfrelease(addressbook)函數釋放addressbook對象,core foundation架構中的資料類型記憶體管理是不受arc管理的,但是與foundation架構的mrc管理類似,需要手動釋放,cfrelease函數就是相當于foundation架構中的release(或autorelease)方法。

viewcontroller.m中的searchbar查詢相關方法:

#pragma mark –uisearchbardelegate 協定方法

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

kabpersonfirstnameproperty,名字

kabpersonlastnameproperty,姓氏

kabpersonmiddlenameproperty,中間名

kabpersonprefixproperty,字首

kabpersonsuffixproperty,字尾

kabpersonnicknameproperty,昵稱

kabpersonfirstnamephoneticproperty,名字漢語拼音或音标

kabpersonlastnamephoneticproperty,姓氏漢語拼音或音标

q kabpersonmiddlenamephoneticproperty,中間名漢語拼音或音标

kabpersonorganizationproperty,組織名

kabpersonjobtitleproperty,頭銜

kabpersondepartmentproperty,部門

kabpersonnoteproperty,備注

讀取記錄屬性函數是abrecordcopyvalue,abrecordcopyvalue函數的定義如下:

abrecordref參數是記錄對象,abpropertyid是屬性id,就是上面的常量kabpersonfirstnameproperty等。傳回值類型是cftyperef,它是core foundation類型的“泛型”,可以代表任何的core foundation類型。

viewcontroller.m中的tableview:cellforrowatindexpath:方法,主要實作了通路單值屬性:

第①行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:方法完成的:

其中第①行代碼調用函數abrecordgetrecordid是擷取選中記錄的id,其中id為abrecordid類型。為了傳遞這個id給detailviewcontroller視圖控制器,detailviewcontroller視圖控制器定義了personidasnumber屬性,在第③行将id給personidasnumber屬性。detailviewcontroller.h代碼如下:

#import <uikit/uikit.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是不能重複的

iOS通路通訊錄開發-讀取聯系人資訊

多值屬性通路方式與單值屬性通路類似都使用abrecordcopyvalue函數。不同的是多值屬性通路傳回值是abmultivalueref,然後要使用abmultivaluecopyarrayofallvalues函數從abmultivalueref對象中擷取數組cfarrayref集合。abmultivaluecopyarrayofallvalues函數的定義如下:

參數multivalue是abmultivalueref對象,index是查找标簽的索引。

abmultivaluegetidentifieratindex函數可以從abmultivalueref對象中傳回id,其定義如下:

其中abmultivaluecopyarrayofallvalues(emailsproperty))語句是從emailsproperty屬性中取出數組集合。kabworklabel和kabhomelabel都是email多值屬性的标簽。kabworklabel是工作email标簽和kabhomelabel是家庭email标簽,另外還有kabotherlabel,它是email标簽。最後emailsproperty需要釋放。

detailviewcontroller.m中的viewdidload方法中取得電話号碼多值屬性代碼如下:

kabpersonphonemobilelabel和kabpersonphoneiphonelabel都是電話号碼屬性的标簽。kabpersonphonemobilelabel是行動電話号碼标簽,kabpersonphoneiphonelabel是iphone電話号碼标簽。此外還有:

kabpersonphonemainlabel,主要電話号碼标簽;

kabpersonphonehomefaxlabel,家庭傳真電話号碼标簽;

kabpersonphoneworkfaxlabel,工作傳真電話号碼标簽;

kabpersonphonepagerlabel,尋呼機号碼标簽。

通訊錄中的聯系人可以有一個圖檔,讀取聯系人圖檔的相關函數有abpersoncopyimagedata和abpersonhasimagedata等。abpersoncopyimagedata可以讀取聯系人圖檔函數,它的定義如下:

它的傳回類型是cfdataref,與之對應的foundation架構類型是nsdata*。abpersonhasimagedata函數用于判斷聯系人是否有圖檔,它的定義如下:

abpersoncopyimagedata取出的是cfdataref類型,将其轉化為nsdata*,再使用uiimage的構造方法imagewithdata:建構uiimage對象,然後再把uiimage對象指派給imageview圖檔控件。