你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> iOS 9 學習系列:Contacts Framework

iOS 9 學習系列:Contacts Framework

編輯:IOS開發基礎

0.jpeg

iOS 9 中,蘋果介紹了新的 Contacts framework。允許用戶使用 Objective-C 的 API 和設備的通訊錄進行交互,同樣適用於 Swift 語言。比起之前通過 AddressBook framework 來讀取聯系人信息來說,這是一個巨大的進步。因為 AddressBook framework 沒有 Objective-C 的 API,非常難用,用 Swift 寫的時候更是痛苦。希望新的 Contacts framework 能夠解決這些痛點。

開發者有多不喜歡 AddressBook framework 呢?我想在 WWDC 的相關 session 裡,當宣布 AddressBook framework 會在 iOS 9 中棄用後,現場爆發了最長時間、最大聲的歡呼,就是最好的證明。

從 Framework 中返回的聯系人是統一的,這意味著,如果你有從不同的數據源來的相同聯系人數據,他們會自動合並,無需手動進行合並的操作。

使用新的 Contacts Framework

現在我們來創建一個簡單的應用。這個應用展示一個你的通訊錄的聯系人列表,同時允許你查看(聯系人的)詳細信息。

blob.png

如果你所見,這是一個 master detail view controller 應用,在 iPhone 同樣可以很好的展示。在左邊是一個你的設備上的聯系人列表,右邊可以看到聯系人的頭像、姓名、電話號碼等詳細信息。

獲取用戶的聯系人

用Xcode 新建一個項目,只需要選擇 master detail view controller 模版就可以開始了。他會給你設置好。

創建好項目後,打開 MasterViewController 類,首先我們要在頭部引入 Contacts 和 ContactsUI 框架。

import Contacts
import ContactsUI

現在我們寫一個方法,填充 datasrouce的特性。這個方法要讀取和展示當前設備通訊錄裡的聯系人。

func findContacts() -> [CNContact] {
let store = CNContactStore()

CNContactStore 是一個用來讀取和保存聯系人的新的類。這篇文章中我們僅僅展示如何讀取聯系人,但是你同樣可以(用此方法)進行展示和保存聯系人群組操作。

let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),
CNContactImageDataKey,
CNContactPhoneNumbersKey]
let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)

當我們有了這個聯系人數據庫的引用後,我們需要創建一個指定條件的請求,通過這個 query 的請求去獲取某些結果。創建一個 CNContactFetchRequest ,我們可以通過設置 contact keys 的數組,來獲取我們需要的結果。有趣的是,我們可以通過CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName) 來格式化。這是CNContactFormattter 的一個非常方便的方法,稍後我們還會用到。

CNContactFormatter 需要很多不同的 keys,如果不使用 descriptorForRequiredKeysForStyle 方法,我們需要手動設置以下的 keys。

[CNContactGivenNameKey,
CNContactNamePrefixKey,
CNContactNameSuffixKey,
CNContactMiddleNameKey,
CNContactFamilyNameKey,
CNContactTypeKey...]

如你所見,要寫一大堆代碼。當 CNContactFormatter key 的需求發生改變,在從CNContactFormatter 生成一個字符串時,你會接到一個異常。

var contacts = [CNContact]()
do {
    try store.enumerateContactsWithFetchRequest(fetchRequest, usingBlock: { (let contact, let stop) -> Void in
    contacts.append(contact)
})
}
catch let error as NSError {
    print(error.localizedDescription)
}
return contacts

這段代碼非常簡單。我們所做的是從 CNContactStore 中遍歷所有符合我們需求的聯系人。這個request 沒有加任何的條件,所以會返回全部的聯系人,包含我們需要的 keys。我們把每一條記錄都逐個保存到一個數組中,返回。

現在我們要調用這個方法,用表格來展示結果。再次打開 MasterViewController, 添加一個屬性,用來展示結果。

var contacts = [CNContact]()

更新 viewDidLoad 方法,用同步的方法調用並存儲結果。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    self.contacts = self.findContacts()
    dispatch_async(dispatch_get_main_queue()) {
        self.tableView!.reloadData()
    }
}

一旦保存好結果,刷新表格。

你需要修改一下 UITableViewDatasource 的方法來展示剛剛得到的結果。

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.contacts.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
    let contact = contacts[indexPath.row] as CNContact
    cell.textLabel!.text = "\(contact.givenName) \(contact.familyName)"
    return cell
}

現在剩下的就是在 DetailViewController 中展示聯系人的詳細信息了。這裡我不在細述,你需要在 DetailViewController 中添加一個圖像視圖、兩個標簽視圖,來展示頭像、姓名和電話號碼。並且在 interface builder 中創建 IBOutlet.

@IBOutlet weak var contactImageView: UIImageView!
@IBOutlet weak var contactNameLabel: UILabel!
@IBOutlet weak var contactPhoneNumberLabel: UILabel!

當這些做完,我們需要設置當前的值。在 configureView ,你需要添加下面這行代碼。

label.text = CNContactFormatter.stringFromContact(contact, style: .FullName)

正如我們之前提到的,CNContactFormatter 能夠很好的格式化聯系人的名字。我們所要做的僅僅是按需求格式化他們,formatter可以很好的控制格式。

在設置頭像時,我們需要先檢測一下 imageData 是否存在。如果設備上的某個聯系人沒有設置頭像, imageData 可能沒有,(不檢測的話)應用會崩潰。

if contact.imageData != nil {
    imageView.image = UIImage(data: contact.imageData!)
} else {
    imageView.image = nil
}

如果存在,我們給 image view 設置好。

最後,我們給電話號碼標簽指定值。

if let phoneNumberLabel = self.contactPhoneNumberLabel {
    var numberArray = [String]()
    for number in contact.phoneNumbers {
        let phoneNumber = number.value as! CNPhoneNumber
        numberArray.append(phoneNumber.stringValue)
    }
    phoneNumberLabel.text = ", ".join(numberArray)
}

這是最終的展示結果。現在,我們擁有一個app,可以在左側,顯示設備上通訊錄中聯系人的列表,並可以逐個找到他的詳細信息。

blob.png

使用 ContactsUI 選擇聯系人

也許我們希望這個應用,可以讓用戶自己選擇聯系人,並且展示詳細信息給我們。正如此前你看到的,這可能要寫很多代碼。如果這些功能已經做好了的,會讓開發變的更加簡單。

這正是 ContactsUI framework 的功能。他提供了一套 view controllers,我們可以用在我們的應用中,展示聯系人的信息。

在這一節,我們想讓用戶可以選擇某個電話號碼,並且保存起來。因為只是一個 demo,所以我們選擇在 MasterViewController 的右上角添加一個 UIBarButtonItem,然後在 MasterViewController 類中,給 UIBarButtonItem 一個方法。

@IBAction func showContactsPicker(sender: UIBarButtonItem) {
    let contactPicker = CNContactPickerViewController()
    contactPicker.delegate = self;
    contactPicker.displayedPropertyKeys = [CNContactPhoneNumbersKey]
    self.presentViewController(contactPicker, animated: true, completion: nil)
}

我們創建了一個簡單的 CNContactPickerViewController ,設置他的代理為 self.這樣我們就能夠響應他的請求,我們感興趣的事電話號碼,盡在選中電話號碼後,展示聯系人信息。CNContactPickerViewController 幫我們控制UI。

func contactPicker(picker: CNContactPickerViewController, didSelectContactProperty contactProperty: CNContactProperty) {
    let contact = contactProperty.contact
    let phoneNumber = contactProperty.value as! CNPhoneNumber
    print(contact.givenName)
    print(phoneNumber.stringValue)
}

在 contactPicker 代理方法 didSelectContactProperty 中,我們復制一個CNContactProperty 對象。這是 CNContact 的一個 wrapper。讓我們來看一下他是怎麼工作的。

blob.png

當我們點擊 MasterViewController 右上角的 UIBarButtonItem 後,會展示一個頁面。這個頁面是所有聯系人的列表,我們沒有添加任何的過濾條件。

blob.png

當你點擊某個聯系人,會展示出這個聯系人的電話列表。正是我們之前CNContactPhoneNumbersKey 裡設置的一樣,這個頁面僅展示了我們需要的關鍵字段。

最後,當你點擊了頁面中某些屬性,例如電話號碼後,會在 picker 關閉前觸發 contactPicker:didSelectContactProperty方法。

在這個例子中,名字叫“Kate Bell”的聯系人是 CNContact 的一個例子。“phoneNumbers”是 key,“5555648583”是 CNPhoneNumber 的值。最後 identifier 字符串作為他的 identifier property.

總結一下,這個例子裡我們使用 ContactsUI framework 來展示選取某個聯系人,是多麼簡單和易用。如果你想開發更加豐富的頁面,更自主的控制頁面的展示信息,Contacts framework 會給你提供很好的獲取數據信息的方式。

延伸閱讀

更多關於 Contacts Framework 的信息,我推薦你觀看WWDC 2015 的 session 223 Introducing the Contacts Framework for iOS and OS X. 最後不要忘了,你可以在 Github 上找到我們已經創建的本篇文章的Demo項目。


  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved