在iOS9中,Apple引入了新的联系人框架。允许用户使用Objective-CAPI与设备的地址簿进行交互,这也适用于Swift语言。与以前通过AddressBook框架读取联系人信息的方式相比,这是一个巨大的改进。因为AddressBook框架没有Objective-CAPI,所以使用起来非常困难,用Swift写的时候就更痛苦了。希望新的Contacts框架能够解决这些痛点。开发人员有多不喜欢AddressBook框架?我想在WWDC的相关环节,当宣布AddressBook框架将在iOS9中被弃用时,现场爆发了最长最响亮的欢呼声,就是最好的证明。Framework返回的联系人是统一的,这意味着如果你有来自不同数据源的相同联系人数据,它们将自动合并,无需手动合并操作。使用新的联系人框架现在让我们创建一个简单的应用程序。此应用程序显示通讯录中的联系人列表,并允许您查看(联系人)的详细信息。contactresult如果你能看到,这是一个masterdetailviewcontroller应用,在iPhone上也能很好的展示。左边是你设备上的联系人列表,右边可以看到联系人的头像、姓名、电话号码等详细信息获取用户的联系人用Xcode新建项目,选择masterdetail即可查看控制器模板开始。他会为你设置的。创建项目后,打开MasterViewController类。首先,我们需要在头文件中引入Contacts和ContactsUI框架。importContactsimportContactsUI现在我们编写一个方法来填充数据源的属性。该方法读取并显示当前设备通讯录中的联系人。funcfindContacts()->[CNContact]{letstore=CNContactStore()CNContactStore是一个用于读取和存储联系人的新类。在本文中我们只展示如何读取联系人,但您也可以(使用此方法)显示和保存联系人组。letkeysToFetch=[CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName),CNContactImageDataKey,CNContactPhoneNumbersKey]letfetchRequest=CNContactFetchRequest(keysToFetch:keysToFetch)当我们有联系人数据库的引用时,我们需要创建一个指定条件的请求,通过这个查询请求到得到一些结果。创建一个CNContactFetchRequest,我们可以通过设置联系键数组来得到我们需要的结果。有趣的是,我们可以通过CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)进行格式化。这是我们稍后会用到的CNContactFormatter的一个非常方便的方法。CNContactFormatter需要很多不同的键,如果我们不使用descriptorForRequiredKeysForStyle方法,我们需要手动设置以下键。[CNContactGivenNameKey,CNContactNamePrefixKey,CNContactNameSuffixKey,CNContactMiddleNameKey,CNContactFamilyNameKey,CNContactTypeKey...]如您所见,需要编写大量代码。当CNContactFormatter键的要求发生变化时,从CNContactFormatter生成字符串时会出现异常。varcontacts=[CNContact]()do{trystore.enumerateContactsWithFetchRequest(fetchRequest,usingBlock:{(letcontact,letstop)->Voidincontacts.append(contact)})}catchleterrorasNSError{print(error.localizedDescription)}returncontacts这段代码很简单。我们所做的是迭代CNContactStore中满足我们需求的所有联系人。这个请求没有添加任何条件,所以它会返回所有的联系人,包括我们需要的密钥。我们将每条记录一条一条保存到一个数组中并返回。现在我们将调用此方法并将结果显示在表格中。再次打开MasterViewController,添加一个属性来显示结果。varcontacts=[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的方法来显示刚刚得到的结果。overridefunctableView(tableView:UITableView,numberOfRowsInSectionsection:Int)->Int{returnsself.contacts.count}overridefunctableView(tableView:UITableView,cellForRowAtIndexPathindexPath:NSIndexPath)->UITableViewCell{letcell=tableView.dequeueReusableCellWithIdentifier("Cell",forIndexPath=)联系人[indexPath.row]asCNContactcell.textLabel!.text="\(contact.givenName)\(contact.familyName)"returncell}现在剩下的就是在DetailViewController中显示联系人详细信息。这里就不细说了,需要在DetailViewController中添加一个imageview和两个labelview来显示头像、姓名和电话号码。并在界面生成器中创建IBOutlet。@IBOutletweakvarcontactImageView:UIImageView!@IBOutletweakvarcontactNameLabel:UILabel!@IBOutletweakvarcontactPhoneNumberLabel:UILabel!完成后,我们需要设置当前值。在configureView中,您需要添加以下代码行。label.text=CNContactFormatter.stringFromContact(contact,style:.FullName)正如我们之前提到的,CNContactFormatter能够很好地格式化联系人姓名。我们要做的就是按照要求对它们进行格式化,格式化程序可以很好地控制格式。在设置头像的时候,我们需要检查imageData是否存在。如果设备上的联系人没有设置头像,则imageData可能没有,并且(如果未检测到)应用程序将崩溃。ifcontact.imageData!=nil{imageView.image=UIImage(data:contact.imageData!)}else{imageView.image=nil}如果存在,我们将其设置为图像视图。***,我们给电话号码标签赋值。ifletphoneNumberLabel=self.contactPhoneNumberLabel{varnumberArray=[String]()fornumberincontact.phoneNumbers{letphoneNumber=number.valueas!CNPhoneNumbernumberArray.append(phoneNumber.stringValue)}phoneNumberLabel.text=",".join(numberArray)}这是最后的显示结果。现在,我们有一个应用程序,可以在左侧设备上显示通讯录中的联系人列表,并可以一个一个地找到他的详细信息。联系人详细信息使用ContactsUI选择联系人也许我们希望此应用程序允许用户选择联系人并向我们显示详细信息。正如您之前看到的,这可能需要大量编码。如果这些功能都已经做好了,开发起来会更容易。这正是ContactsUI框架所做的。它提供了一组视图控制器,我们可以在我们的应用程序中使用它们来显示联系信息。在本节中,我们希望用户能够选择电话号码并保存。因为只是demo,所以我们选择在MasterViewController的右上角添加一个UIBarButtonItem,然后在MasterViewController类中给UIBarButtonItem一个方法。@IBActionfuncshowContactsPicker(sender:UIBarButtonItem){让contactPicker=CNContactPickerViewController()contactPicker.delegate=self;contactPicker.displayedPropertyKeys=[CNContactPhoneNumbersKey]self.presentViewController(contactPicker,animated)我们创建了一个简单的:true,CNContactPickerViewController,设置他的代理为self。为了响应他的请求,我们对电话号码感兴趣,只有选择电话号码后,才会显示联系信息。CNContactPickerViewController帮助我们控制UI。funccontactPicker(picker:CNContactPickerViewController,didSelectContactPropertycontactProperty:CNContactProperty){letcontact=contactProperty.contactletphoneNumber=contactProperty.valueas!CNPhoneNumberprint(contact.givenName)print(phoneNumber.stringValue)}在contactPicker代理方法didSelectContactProperty中,我们复制一个CNContactProperty对象。ThisisaCNContact的包装器。让我们看看它是如何工作的。contactpicker当我们点击MasterViewController右上角的UIBarButtonItem时,会显示一个页面。此页面是所有联系人的列表,我们没有添加任何过滤条件。contactselected当您点击一个联系人时,将显示该联系人的电话列表。就像我们之前在CNContactPhoneNumbersKey中设置的一样,这个页面只展示了我们需要的关键字段。***,当你点击页面上的某个属性时,比如电话号码,contactPicker:didSelectContactProperty方法将在选择器关闭之前被触发。在此示例中,名为“KateBell”的联系人是CNContact的一个实例。“phoneNumbers”是键,“5555648583”是CNPhoneNumber的值。***标识符字符串作为其标识符属性。综上所述,在本示例中,我们使用ContactsUI框架来展示选择联系人是多么简单和容易。如果你想开发更丰富的页面,更自主地控制页面的显示信息,Contacts框架将为你提供获取数据信息的好方法。要阅读有关联系人框架的更多信息,我建议您观看WWDC2015session223IntroducingtheContactsFrameworkforiOSandOSX。***别忘了,您可以在Github项目上找到我们为本文创建的演示。
