从 iOS9 开始 Apple 对联系人进行了重构,使用了 Contacts.framework。新的架构相对于之前的架构,获取联系人的方式更加灵活,并且因为是 OC (Swift)接口使用起来更加方便。
相对于老的架构,新的架构需要注意的地方主要有一下几点:
- 新的架构读取联系人的时候需要提前指定需要获取的数据范围(在 CNContactFetchRequest 中)
- 新的架构允许通过 NSPredicate 来获取或匹配联系人
- 新的架构中,联系人的位置标识符从数值变成了字符串
- 获取联系人的 fullName 的时候 AB 架构使用
ABRecordCopyCompositeName
即可。新的架构需要使用[CNContactFormatter stringFromContact:contact style:CNContactFormatterStyleFullName]
,这里需要注意,使用 CNContactFormatter 来格式化联系人名称时同样需要在 CNContactFetchRequest 中声明,否则会抛异常。声明的方式为 :
// [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]用于声明请求使用 CNContactFormatter 来获取联系人的 fullName
[[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactIdentifierKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]]];
关于 Label
Label 是联系人中用来区分同一个联系人下面不同号码通途的。联系人架构预设了一些 Label 如:工作,住宅等。
这些预设的 Label 在 AB 架构和新的架构中都有统一的格式 _$!<Home>!$_
,对于这些预设的 Label 可以通过系统接口来转换成本地化的语言描述。这些接口是 ABAddressBookCopyLocalizedLabel
或 [CNLabeledValue localizedStringForLabel:label]
。如,参数为 _$!<Home>!$_
则转化成中文后为 “家庭” (住宅)。
对于用户自定义的 Label 则没有这种特殊结构,用户定义的是什么,接口就返回什么。
可以通过如下代码获取到原始的 Label
// 9 之前
CFStringRef label = ABMultiValueCopyLabelAtIndex(record, index);
CFRelease(label);
// 9 之后
CNLabeledValue<CNPhoneNumber *> *currentNumber = SomeNumber;
NSString *label = currentNumber.label;