訪問地址簿和單個連絡人資料的介面是基於C語言的函數,介面傳遞對地址簿各種對象的引用作為參數。管理地址簿中條目的基類對象是 ABRecord。一個 ABRecord 可以表示一個人 或者一個群體 ABGroup 。無論何時,在介面上選中一條記錄,或者使用架構進行查詢返回一條結果,系統都會返回一個指向 ABRecord 的指標,標示為 ABRecordRef。與地址簿 API 的大部分互動都涉及使用 ABRecordRef 這個參考型別。
常用訪問記錄的函數如下:
ABRecordID ABRecordGetRecord(ABRecordRef record);
返回 ABRecordID ,代表了 記錄在底層資料庫中的ID號。具有唯一性。
ABRecordType ABRecordGetRecordType(ABRecordRef record);
返回記錄類型。可以是 kABPersonType 和 kABGroupType
CFStringRef ABRecordCopyCompositeName(ABRecordRef record);
返回個人或群體完整名稱。例:NSString* name = (NSString*)ABRecordCopyCompositeName(record);
一、高層地址簿函數
1.獲得地址簿控制代碼
你必須先初始化地址簿,然後才能對其進讀寫操作。要獲得一個地址簿控制代碼,可以使用 ABAddressBookCreate函數:
#import <AddressBook/AddressBook.h>AddressBookRef ab = AddressBookCreate();
2. 儲存地址簿
獲得了地址簿的引用就可以對其進行操作了,操作完畢要記得儲存:
CFErrorRef err;BOOL success = ABAddressBookSave(ab, &err);
如果不確定是否需要儲存,則可以用:
BOOL hasUnsavedChanges = ABAddressBookHasUnsavedChanges(ab);
3.添加/刪除 記錄
CFErrorRef err; BOOL success =ABAddressBookAddRecord(ab, record, &err);//添加
CFErrorRef err; BOOL success =ABAddressBookRemoveRecord(ab, record, &err);//刪除
二、查詢地址簿
地址簿架構僅僅提供了基本的查詢功能。可以用函數根據名字來查詢多個記錄,或者是根據特定記錄 ID 查詢單個記錄。
1.擷取地址簿中記錄總個數:
CFIndex count = ABAddressBookGetPersonCount(ab); printf("%ld total entries in the address book\n",count);
2. 擷取所有連絡人:
NSArray* array = (NSArray*)ABAddressBookCopyArrayOfAllPeople(ab); printf("Retrieved %d contacts\n",[array count]);
3. 在連絡人清單中查詢一個特定的名字:
NSArray* arrayByName = (NSArray*)ABAddressBookCopyPeopleWithName(ab, CFSTR("Liu Wei"));
函數如其名,這個函數返回的並不是地址簿中實際的對象,而是拷貝。要訪問這個數組的單個記錄,就用NSArray的方法啦:
ABRecordRef myRecord = [arrayByName objectAtIndex:0];
除了通過名字查詢,你也可以直接通過ID查詢(假如你知道ID的話):
ABRecordRef myRecord = ABAddressBookGetPersonWithRecordID(ab, recordID);
三、建立記錄
建立新的連絡人可以使用 ABPersonCreate 函數。這樣可以得到一個空記錄,然後就可以向其中填充資訊:
ABRecordRef record = ABPersonCreate();
四、操縱記錄
一旦獲得了 ABRecordRef,就可以確定是屬於個人還是群體,也就可以訪問更進一步的資訊了。姓名以及其他各項資訊都可以通過相應屬性來操縱。只有ABPerson 類型實體記錄才會有屬性,而每個記錄都具有各種各樣的資訊。
查詢給定記錄的資訊,可以使用 ABRecordCopyValue 函數。這個函數原型如下:
CFTypeRef ABRecordCopyValue(ABRecordRef record,kABPersonFirstNameProperty);
調用這個函數時,會將你指定 的屬性拷貝一份,並返回引用:
CFStringRef firstName = ABRecordCopyValue(record, kABPersonFirstNameProperty);
由於kABPersonFirstNameProperty 屬性是一個 CFString,你可以將其轉換為 NSString* :
NSString* firstName =NSString* ABRecordCopyValue(record, kABPersonFirstNameProperty);
就像CFStringRef 可以轉換為 NSString* 一樣,如果有屬性傳回型別是CFDateRef,你也可以轉換為 NSDate* :
NSDate* birthday = (NSDate*) ABRecordCopyValue(record, kABPersonBirthdayProperty);
上面所指定的 ABPropertyID, 是一個與在記錄中尋找資訊相對應的值。根據這個值返回ABPerson
對象屬性。由於 ABRecordCopyValue 函數返回的資料類型是通用的 CFTypeRef ,所以結果可疑被轉換為一個與屬性相對應的更細化的資料類型,如下表:
// Property keysextern const ABPropertyID kABPersonFirstNameProperty; // First name - kABStringPropertyTypeextern const ABPropertyID kABPersonLastNameProperty; // Last name - kABStringPropertyTypeextern const ABPropertyID kABPersonMiddleNameProperty; // Middle name - kABStringPropertyTypeextern const ABPropertyID kABPersonPrefixProperty; // Prefix ("Sir" "Duke" "General") - kABStringPropertyTypeextern const ABPropertyID kABPersonSuffixProperty; // Suffix ("Jr." "Sr." "III") - kABStringPropertyTypeextern const ABPropertyID kABPersonNicknameProperty; // Nickname - kABStringPropertyTypeextern const ABPropertyID kABPersonFirstNamePhoneticProperty; // First name Phonetic - kABStringPropertyTypeextern const ABPropertyID kABPersonLastNamePhoneticProperty; // Last name Phonetic - kABStringPropertyTypeextern const ABPropertyID kABPersonMiddleNamePhoneticProperty; // Middle name Phonetic - kABStringPropertyTypeextern const ABPropertyID kABPersonOrganizationProperty; // Company name - kABStringPropertyTypeextern const ABPropertyID kABPersonJobTitleProperty; // Job Title - kABStringPropertyTypeextern const ABPropertyID kABPersonDepartmentProperty; // Department name - kABStringPropertyTypeextern const ABPropertyID kABPersonEmailProperty; // Email(s) - kABMultiStringPropertyTypeextern const ABPropertyID kABPersonBirthdayProperty; // Birthday associated with this person - kABDateTimePropertyTypeextern const ABPropertyID kABPersonNoteProperty; // Note - kABStringPropertyTypeextern const ABPropertyID kABPersonCreationDateProperty; // Creation Date (when first saved)extern const ABPropertyID kABPersonModificationDateProperty; // Last saved date
五、寫入屬性
向記錄寫入屬性,使用ABRecordSetValue 函數:
CFStringRef name = CFSTR("IUKEY"); BOOL suc = ABRecordSetValue(record, kABPersonNicknameProperty, name, &err); if (suc) { NSLog(@"setValue succeed"); }
刪除屬性:
BOOL succeed = ABRecordRemoveValue(record, kABPersonFirstNameProperty, &err);
當修改完以後不要忘記儲存地址簿。
六、多值屬性
除了前面列出的屬性之外,一個記錄還可能會有一些屬性,其中包含多個值。多隻屬性可以用一種索引機制來處理,使用時首先查詢值的總數,然後通過特定的索引得到一個條目。指向多值資料的指標,可以首先通過前面提到的 ABRecordCopyValue 方法得到,然後轉換成 MultiValueRef :
ABMultiValueRef phoneNumbers = ABRecordCopyValue(record, kABPersonPhoneProperty);
然後你可以通過這個引用來確定值的個數,並按照索引擷取其中的單個值。函數ABMultiGetCount 可以返回條目個數,按照索引拷貝指定條目,可以用ABMultiValueCopyValueAtIndex 函數。
下面列出了多值屬性中的條目:
extern const ABPropertyID kABPersonEmailProperty;extern const ABPropertyID kABPersonAddressProperty;extern const ABPropertyID kABPersonDateProperty; extern const ABPropertyID kABPersonPhoneProperty;extern const ABPropertyID kABPersonInstantMessageProperty; extern const ABPropertyID kABPersonURLProperty;
除了多值屬性中真正的值,每個條目還有一個標籤。標籤描述了返回的條目的類型。例如,一個電話號碼標籤有可能指明了這個號碼是家庭電話還是手機號。地址的標籤則可一描述是家庭地址還是工作地址。要查詢特定條目標籤,可以使用 ABMultValueCopyLabelAtIndex 函數:
CFStringRef label = ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
默寫屬性具有一組預定義的標籤。下面這些 CFStringRef 類型標籤的原型是在 ABPerson.h 中指定的:
extern const ABPropertyID kABPersonDateProperty; // Dates associated with this person - kABMultiDatePropertyTypeextern const CFStringRef kABPersonAnniversaryLabel;
// Phone numbersextern const ABPropertyID kABPersonPhoneProperty; // Generic phone number - kABMultiStringPropertyTypeextern const CFStringRef kABPersonPhoneMobileLabel;extern const CFStringRef kABPersonPhoneIPhoneLabel __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);extern const CFStringRef kABPersonPhoneMainLabel;extern const CFStringRef kABPersonPhoneHomeFAXLabel;extern const CFStringRef kABPersonPhoneWorkFAXLabel;extern const CFStringRef kABPersonPhoneOtherFAXLabel __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);extern const CFStringRef kABPersonPhonePagerLabel;
// IMextern const ABPropertyID kABPersonInstantMessageProperty; // Instant Messaging - kABMultiDictionaryPropertyTypeextern const CFStringRef kABPersonInstantMessageServiceKey; // Service ("Yahoo", "Jabber", etc.)extern const CFStringRef kABPersonInstantMessageServiceYahoo;extern const CFStringRef kABPersonInstantMessageServiceJabber;extern const CFStringRef kABPersonInstantMessageServiceMSN;extern const CFStringRef kABPersonInstantMessageServiceICQ;extern const CFStringRef kABPersonInstantMessageServiceAIM;
// URLsextern const ABPropertyID kABPersonURLProperty; // URL - kABMultiStringPropertyTypeextern const CFStringRef kABPersonHomePageLabel; // Home Page
// Related namesextern const ABPropertyID kABPersonRelatedNamesProperty; // Names - kABMultiStringPropertyTypeextern const CFStringRef kABPersonFatherLabel; // Fatherextern const CFStringRef kABPersonMotherLabel; // Motherextern const CFStringRef kABPersonParentLabel; // Parentextern const CFStringRef kABPersonBrotherLabel; // Brotherextern const CFStringRef kABPersonSisterLabel; // Sisterextern const CFStringRef kABPersonChildLabel; // Childextern const CFStringRef kABPersonFriendLabel; // Friendextern const CFStringRef kABPersonSpouseLabel; // Spouseextern const CFStringRef kABPersonPartnerLabel; // Partnerextern const CFStringRef kABPersonAssistantLabel; // Assistantextern const CFStringRef kABPersonManagerLabel; // Manager
許多屬性使用一組通用標籤,標識工作、家庭以及其它地點。這些通用的標籤如下:
kABWorkLabel
kABHomeLabel
kABOtherLabel
寫入多隻屬性條目:
為了在現有的屬性中加入一個值,你必須首先從屬記錄中複製出多值字典。然後 ABMultiValueAddValueAndLabel 函數操作拷貝,將新的值-標籤加入到字典中。最後用函數 ABRecordSetValue 將字典條目寫回到地址簿記錄中,完全替換掉整個多值屬性。
七、使用字典
地址簿記錄用字典來 表示地址和即時通訊帳號。這些字典是內嵌在多值屬性條目之中的。要訪問這些字典,需要將值複製出來,並轉換成 NSDictionary* 。然後你就可以用一組預定於的索引值來訪問字典了。
八、映像資料
某些連絡人可能會有與之相關聯的映像。可以使用 ABPersonCopyImageData 函數擷取這些映像資料,返回將是一個 CFDataRef。可以把它轉換成 NSData*,然後用來初始化一個UIImage對象。
if (ABPersonHasImageData(record)) { UIImage *addressVookImage = [UIImage imageWithData:(NSData*)ABPersonCopyImageData(record)]; }
九、地址簿介面
地址簿介面架構提供了兩種關鍵的使用者介面:一個“找人”導航控制項,來選擇連絡人;以及一個視圖控制項,用於顯示單個連絡人。
1. 連絡人視圖
ABPersonViewController 提供了一個簡單的介面,可以向使用者顯示一個連絡人。連絡人視圖需要一個 CFRecordRef 。
ABPersonViewController *viewController = [[ABPersonViewController alloc]init];
可以將希望顯示的記錄賦值給 displayedPerson 屬性:
viewController.displayedPerson=record;
然後,你可以建立一個數組,其中包含你想要顯示給使用者的屬性。只有指定的屬性才會被顯示出來,不過如果連絡人被修改了,所有屬性都將顯示出來。可用的屬性值與前面提到的枚舉值相同。每個都作為一個 NSNumber 對象加入到數組中。
NSMutableArray* properties = [[NSMutableArray alloc]init]; [properties addObject:[NSNumber numberWithInt:kABPersonFirstNameProperty ]]; [properties addObject:[NSNumber numberWithInt:kABPersonLastNameProperty ]]; [properties addObject:[NSNumber numberWithInt:kABPersonOrganizationProperty ]]; viewController.allowsEditing =YES;
十、連絡人選取器
如果應用程式要選取一系列連絡人,ABPeoplePickerNavigationController 類正好適合你。這個導航控制項 可以顯示連絡人,讓使用者從中選擇其一。選好後,你可以選擇向使用者顯示該連絡人,也可以通過一個委託方法實現你自己的行為。
ABPeoplePickerNavigationController* peoplePicker = [[ABPeoplePickerNavigationController alloc]init];
如果希望允許使用者查看單個連絡人,你可以賦予其一組希望使用者看到的屬性。預設情況下會向使用者顯示所有的項目。 可用的屬性值就是本章前面講授的那些枚舉值。每個作為一個NSNumber對象加入到數組中:
NSMutableArray* properties = [[NSMutableArray alloc]init]; [properties addObject:[NSNumber numberWithInt:kABPersonFirstNameProperty ]]; [properties addObject:[NSNumber numberWithInt:kABPersonLastNameProperty ]]; [properties addObject:[NSNumber numberWithInt:kABPersonOrganizationProperty ]]; peoplePicker.displayedProperties = properties;
可以指定一個委託,在使用者選定連絡人時接收通知:
peoplePicker.peoplePickerDelegate =self;
[self.view addSubview:peoplePicker.view];
委託方發:
-(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{ //取消選擇}-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person{ //選中連絡人 }-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{ //選中屬性}