這個全新的聯系人框架,簡單易用,使用它可以很容易地查找、創建和更新聯系人信息,而且這個framework對thred-safe、read-only usage方面進行了優化。iOS和OS X平臺都可用,用來代替之前的AddressBook framework。
翻譯自官方文檔Contacts Framework Reference。
聯系人對象

CNContact
表示一條聯系人記錄,包含聯系人的name、image、phone numbers.
這個類像NSDictionary一樣;擁有一個可變的子類CNMutableContact
,你可以使用它修改聯系人屬性。而這些屬性可以擁有多個值,例如phone numbers或者email addresses,這些就是一組CNLabeledValue
對象的數組。這個labeled value對象是線程安全的,由不可變labels和values的元組組成。Contacts framework提供一些預先定義的labels,你也可以創建自定義的labels。
創建一個聯系人:
import Contacts
// Creating a mutable object to add to the contact
let contact = CNMutableContact()
contact.imageData = NSData() // The profile picture as a NSData object
contact.givenName = "John"
contact.familyName = "Appleseed"
let homeEmail = CNLabeledValue(label:CNLabelHome, value:"john@example.com")
let workEmail = CNLabeledValue(label:CNLabelWork, value:"j.appleseed@icloud.com")
contact.emailAddresses = [homeEmail, workEmail]
contact.phoneNumbers = [CNLabeledValue(
label:CNLabelPhoneNumberiPhone,
value:CNPhoneNumber(stringValue:"(408) 555-0126"))]
let homeAddress = CNMutablePostalAddress()
homeAddress.street = "1 Infinite Loop"
homeAddress.city = "Cupertino"
homeAddress.state = "CA"
homeAddress.postalCode = "95014"
contact.postalAddresses = [CNLabeledValue(label:CNLabelHome, value:homeAddress)]
let birthday = NSDateComponents()
birthday.day = 1
birthday.month = 4
birthday.year = 1988 // You can omit the year value for a yearless birthday
contact.birthday = birthday
// Saving the newly created contact
let store = CNContactStore()
let saveRequest = CNSaveRequest()
saveRequest.addContact(contact, toContainerWithIdentifier:nil)
try store.executeSaveRequest(saveRequest)
格式和本地化
Contacts framework可以幫助你格式和本地化聯系人信息。例如,你可以準確無誤地格式一個聯系人name(使用CNContactFormatter),或者格式一個國際郵政地址(使用CNPostalAddressFormatter)
格式聯系人name和郵政地址
// Formatting contact name
let fullName = CNContactFormatter.stringFromContact(contact, style: .FullName)
print(fullName)
// John Appleseed
// Formatting postal address
let postalString = CNPostalAddressFormatter.stringFromPostalAddress(homeAddress)
print(postalString)
// 1 Infinite Loop
// Cupertino
// CA
// 95014
你可以通過設備當前的本地設置本地化展示對象的names屬性和預先設定的labels。
CNContact類包含localizedStringForKey:
方法,它可以通過key值獲取本地化的譯本。而CNLabeledValue類包含localizedStringForLabel:
方法,它可以通過預先設定的labels獲取本地化的label,從而獲取相應的信息。
本地化的name:
// device locale is Spanish
let displayName = CNContact.localizedStringForKey(CNContactNicknameKey)
print(displayName)
// alias
let displayLabel = CNLabeledValue.localizedStringForLabel(CNLabelHome)
print(displayLabel)
// casa
獲取聯系人
你可以使用聯系人倉庫(CNContactStore),也就是用戶聯系人的數據庫來獲取聯系人。聯系人數據庫的方法是同步的,這就需要你在后臺線程使用它們。而后在主線程中返回獲取到的結果。
Contacts framework提供幾種方法檢索聯系人,包括predicates和keysToFetch
。
通過predicates獲取聯系人:
let predicate: NSPredicate = CNContact.predicateForContactsMatchingName("Appleseed")
通過KeysToFetch
獲取聯系人:
let keysToFetch = [CNContactGivenNameKey,CNContactFamilyNameKey]
如何獲取聯系人:
let store = CNContactStore()
let contacts = try store.unifiedContactsMatchingPredicate(CNContact.predicateForContactsMatchingName("Appleseed"), keysToFetch:[CNContactGivenNameKey, CNContactFamilyNameKey])
Contacts framework也可以在獲取到的聯系人上執行操作,例如格式聯系人name。每次執行操作都需要特定的keys來保證其準確無誤。這些keys是特定的key描述對象,包含在keysToFetch之內。
通過key值描述獲取聯系人:
let keysToFetch = [CNContactEmailAddressesKey, CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)]
隱私
用戶可以允許或者拒絕訪問聯系人數據。其中為了避免APP UI的主線程獲取,你要么使用異步方法[CNContactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:]
,要么派遣你的CNContactStore
內存到后臺線程。
局部聯系人
一個局部聯系人僅僅只有一些從聯系人數據庫獲取來的屬性值。所有獲取到的聯系人對象都是局部聯系人。如果你使用一個沒有獲取到的屬性值,將會拋出異常。如果你不確定keys在聯系人中是否被獲取到,在使用它們之前最好先檢查其可用性。你可以使用isKeyAvailable:
去檢查單個聯系人key的可用性,也可以使用areKeysAvailable:
去檢查多個keys。如果檢查的keys不可用就需要重新獲取。
使用isKeyAvailable
檢查key的可用性:
// Checking if phone number is available for the given contact.
if (contact.isKeyAvailable(CNContactPhoneNumbersKey)) {
print("\(contact.phoneNumbers)")
} else {
//Refetch the keys
let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey]
let refetchedContact = try store.unifiedContactWithIdentifier(contact.identifier, keysToFetch: keysToFetch)
print("\(refetchedContact.phoneNumbers)")
}
整合聯系人

每一個獲取的整合聯系人(CNContact)對象都有它自己獨一無二的標識符,它與其他一連串聯系人的標識符都不同。重新獲取一個整合的聯系人應該通過它的標識符來完成。
保存聯系人
CNSaveRequest
類可以實現保存操作而且允許批量修改多個聯系人和分組。
注意:不要在save request中使用正在執行保存的對象,因為它可能已經被修改。
保存一個新的聯系人:
// Creating a new contact
let newContact = CNMutableContact()
newContact.givenName = "John"
newContact.familyName = "Appleseed"
// Saving contact
let saveRequest = CNSaveRequest()
saveRequest.addContact(newContact, toContainerWithIdentifier:nil)
try store.executeSaveRequest(saveRequest)
保存一個修改的聯系人:
let mutableContact = contact.mutableCopy() as! CNMutableContact
let newEmail = CNLabeledValue(label: CNLabelHome, value: "john@example.com")
mutableContact.emailAddresses.append(newEmail)
let saveRequest = CNSaveRequest()
saveRequest.updateContact(mutableContact)
try store.executeSaveRequest(saveRequest)
聯系人被改變通知
在save執行成功之后,聯系人數據庫提交一個CNContactStoreDidChangeNotification
通知到通知者中心。如果你緩存了所有的聯系人對象,你需要重新獲取它們,要么使用它們的標識符,要么通過最初獲取的predicates來重新獲取,而且你需要釋放掉緩存的對象。注意緩存的對象是舊的但不一定是無效的。
容器和群組
用戶可以同步本地設備的聯系人和服務器的聯系人。每個賬戶至少有一個聯系人容器,一個聯系人也只能出現在一個容器里面。

一系列聯系人組成的群組在一個容器里面。不是所有賬戶都支持群組,一些賬戶可能支持子群。一個iCloud賬戶只有一個容器,它可以有很多群組但沒有子群。

類組成
- CNContact:表示一個聯系人,包含聯系人的name、image、phone numbers,不可變;
- CNMutableContact:CNContact的子類,表示具有可變屬性的聯系人;
- CNContactFetchRequest:用于獲取聯系人;
- CNContactProperty:關于聯系人的property的類,含有contact、key、value、label以及identifier;
- CNContactRelation:表示一個聯系人與另一個關系的不可變值對象;
- CNContactStore:聯系人倉庫,可以獲取、保存聯系人,與群組、容器有關;
- CNContactVCardSerialization:提供vCard表示給定的一系列的聯系人;
- CNContactsUserDefaults:聯系人user defaults使用過的properties;
- CNContainer:聯系人容器,不可變;
- CNGroup:聯系人群組,不可變;
- CNMutableGroup:CNGroup的子類,表示可變的聯系人群組;
- CNInstantMessageAddress:表示一個當前消息地址;
- CNLabeledValue:聯合一個label的聯系人屬性值;
- CNPhoneNumber:表示一個聯系人的phone number;
- CNPostalAddress:表示一個聯系人的郵政地址;
- CNMutablePostalAddress:CNPostalAddress的子類,表示可變的聯系人郵政地址;
- CNSaveRequest:表示一個聯系人保存操作請求;
- CNSocialProfile:表示社會簡況;
- CNContactFormatter:NSFormatter的子類,定義不同的聯系人格式風格;
- CNPostalAddressFormatter:聯系人郵政地址格式;
擴展
如果想了解更多關于Contacts Framwork
的信息,推薦觀看WWDC2015大會上的視頻Introducing the Contacts Framework for iOS and OS X。
- 檢查應用是否準許訪問聯系人,并且如何請求授權。
- 使用三種不同的方式檢索聯系人。其中一種方式將會涉及 Picker View Controller 的使用。
- 訪問檢索到的聯系人屬性,并調整為適當的顯示格式。
- 使用默認的 Contacts UI 來實現選擇、查看以及編輯聯系人。
- 創建一個新的聯系人