[CS193P] 第十三堂課摘要及心得筆記

在這一堂的課程中,我們將學到如何在Cocoa Touch上使用Core Foundation和AddressBook這兩個Framework將我們的應用程式與iPhone OS上的通訊錄做結合,創造出更多有趣的應用程式。就讓我們一起來看看吧!
評論
評論

在這一堂的課程中,我們將學到如何在 Cocoa Touch 上使用 Core Foundation 和 AddressBook 這兩個 Framework 將我們的應用程式與 iPhone OS 上的通訊錄做結合,創造出更多有趣的應用程式。就讓我們一起來看看吧!

Core Foundation

Core Foundation 是 Cocoa Touch 底層的 Framework,以 C 語言為主。其所提供的功能就如同我們常常使用的 Foundation Framework 一般,一樣有提供 Array、String、Dictionary 等 API。例如:

  • NSArray => CFArrayRef
  • NSString => CFStringRef
  • retain = CFRetain
  • release = CFRelease

事實上,大多數的 Foundation Framework API 底層也是透過 Core Foundation 實做的。因此,幾乎兩個 Framework 的函式和物件都可以通用,如下方程式片段:

CFArrayRef array = ABAddressBookCopyPeopleWithName(...); NSLog(@“%d”, [(NSArray *)array count]); NSMutableArray *mutableArray = [(NSArray *)array mutableCopy]; [mutableArray release]; if (array) {     CFRelease(array); }

而在記憶體管理上,Core Foundation 所提供的物件也都有 retain count 的概念,物件一樣在使用完畢後也得 release 才行。在 Core Foundation 的命名慣例上,所有以 Create 結尾的函式都會回傳已經 retain 過的物件。

值得注意的是,C 語言並不像 Objective-C 一樣可以對 nil 物件呼叫函式,在 C 語言中,所有的函式呼叫都要先檢查是否不等於 NULL:

CFStringRef string = CreateSomeCFString...; if (string != NULL) {     DoSomethingWith(string);     CFRelease(string); }

當然我們也可以使用 Foundation Framework 來操作,方便許多:

NSString *string = (NSString *)CreateSomeCFString...; NSLog(@“%@”, [string lowercaseString]); [string autorelease]; // autorelease 也可以使用

那 為什麼我們要談 Core Foundation 呢?原因是 AddressBook Framework 也是以 C 語言為基礎,所回傳的物件也都是 Core Foundation 的物件,所以在我們使用 AddressBook 的 API 之前,必須要先熟悉 Core Foundation 的一些使用方法。

AddressBook

在這次的課程中,講者透過打造一個社群網路的網站作為主軸,向大家示範 AddressBook 的使用方式。而這個應用程式的運作流程為如下:

  1. 從網路下載資料
  2. 搜尋本機中是否已經有對應的聯絡人
  3. 更新資料
  4. 顯示資料

在進行後續步驟之前,我們必須先建立 AddressBookRef 的物件,這個物件會協助我們連接通訊錄所儲存的資料庫,而這個資料庫是全系統共通的,換句話說,我們可以建立很多 AddressBookRef,但最後都是存取同一份資料。如下段程式碼所示:

ABAddressBookRef ab = ABAddressBookCreate();

而在 AddressBook 中,每一筆聯絡人的資料就是 ABRecordRef,這裡面包含了聯絡人的所有 properties,像是姓名、電話或是頭像等等。每個 property 會有不同的型別,像是 CFString、CFDate 等等。而有些 property 會有多重 value,像是 E-mail 就又可以分成工作的 E-mail 和私人的 E-mail。這些 properties 都被定義在 ABPerson.h 裡面,有興趣的讀者還可以參考。

對於只有單一 value 的 property,可以使用以下程式片段:

CFStringRef first = ABRecordCopyValue(person, kABPersonFirstNameProperty); // 獲得 property CFDateRef date = CFDateCreate(...); ABRecordSetValue(person, kABPersonBirthdayProperty, date, &error); // 設定 property

ABMultiValueRef 則是用來處理多重 value 的 property 類別,以一個樹狀的結構呈現,每個不同的 value 都會有相對應的 label,如下圖所示:

而我們可以透過以下 API 來取得資料:

  • CFIndex count = ABMultiValueGetCount(multiValue); // 有多少不同 value
  • CFTypeRef value = ABMultiValueCopyValueAtIndex(mv, index); // 取得 value
  • CFStringRef label = ABMultiValueCopyLabelAtIndex(mv, index); // 取得 label
  • CFIndex identifier = ABMultiValueGetIdentifierAtIndex(mv, index); // 取得 identifier

也可以透過以下 API 儲存資料,除了設定聯絡人的 property 之外,我們也需要將整個 AddressBook 存回系統:

ABMultiValueRef urls = ABRecordCopyValue(person, kABPersonURLProperty); // 取得原有的 URL property ABMutableMultiValueRef urlCopy = ABMultiValueCreateMutableCopy(urls); // 建立新的 URL property ABMultiValueAddValueAndLabel(urlCopy, "the url", "social", NULL); // 加入新的 value 和 label ABRecordSetValue(person, urlCopy, kABPersonURLProperty); // 將新的 URL property 存回聯絡人 ABAddressBookSave(ab, &err); // 將整個 AddressBook 存回系統資料庫

而當完成更新資料後,下一個動作就是要在畫面上顯示聯絡人,而在顯示之前,可以先做排序:

CFMutableArrayRef people = // 取得存放聯絡人的 array CFRange fullRange = CFRangeMake(0, CFArrayGetCount(people)); ABPersonSortOrdering sortOrdering = ABPersonGetSortOrdering(); CFArraySortValues(people, fullRange, ABPersonComparePeopleByName, (void*)sortOrdering);

也可以透過 Objective-C 的 Framework:

[people sortUsingFunction:ABPersonComparePeopleByName context: (void*)sortOrdering];

而最後,AddressBook 也提供了 ABRecordCopyCompositeName(person); 以取得使用者的名稱。

以上大概就是簡單的 AddressBook 操作流程。

PersonViewController

當我們需要顯示 ABPerson 的詳細資料時,ABPesonViewController 就會提供很好的幫助,如下圖:

而 ABPersonViewController 有以下幾種 Property:

  • displayedPerson -- 顯示的 person
  • displayedProperties -- 顯示的 properties
  • allowsEditing -- 是否允許修改

而當我們要新增聯絡人資料時,則可以使用 ABUnknownPersonViewController,當使用者編輯完成之後,會呼叫 delegate 的方法:

- (void)unknownPersonViewController:(ABUnknownPersonViewController *) unknownCardViewController didResolveToPerson:(ABRecordRef)person

透過以上這兩個 View Controller,我們就可以完成 AddressBook 中 Person 的顯示和新增,更多資料請參考 AddressBook Programming Guide for iPhone OS

ABPeoplePickerNavigationController

除了顯示 AddressBook 的 Person 之外,有時我們也得提供使用者一個選擇的清單,而這個介面就可以透過 ABPeoplePickerNavigationController 來完成,如下圖:

想必大家在 iPhone 平台上開發也有一段時間了,自然可以猜想到這個類別也提供了很多 delegate 方法,像是當使用者選擇了聯絡人或者是取消時,都會呼叫對應的 delegate 方法。

更多的內容請參考 ABPeoplePickerNavigationController Class Referecne

結論

在這一次的課程中,我們獲得了許多關於 Core Foundation 和 AddressBook 的基本觀念,透過這兩個 Framework 我們可以將 iPhone 的通訊錄整合到我們的應用程式中,而不需要另外自行建立資料庫及相關程式。在下一次的課程中,內容將會轉移到 iPhone 上的多點觸控事件以及相關的使用方法,還請各位讀者敬請期待!

參考資源