这个全新的联系人框架,简单易用,使用它可以很容易地查找、创建和更新联系人信息,而且这个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 来实现选择、查看以及编辑联系人。
- 创建一个新的联系人