iosswiftcontacts-framework

How to use CNContactPickerViewController to get address AND contact?


I am trying to use the more modern CNContactPickerViewController to select a contact. If the contact has multiple addresses, I want the user to be able to select only one of the addresses. If an address is specifically selected, I want to also get the CNContact object as well.

I could do this using the deprecated ABPeoplePickerNavigationControllerDelegate, where this delegate function was available:

func peoplePickerNavigationController(_ peoplePicker: ABPeoplePickerNavigationController, didSelectPerson person: ABRecord, property: ABPropertyID, identifier: ABMultiValueIdentifier)

However, when using CNContactPickerViewController, only this relevant delegate function is available:

func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty)

Note that there is no CNContact object returned. I get the CNPostalAddress in the contactProperty, but I don't receive the record of the owning contact.

Here's the code I used with ABPeoplePickerNavigationController:

    let peoplePicker = ABPeoplePickerNavigationController()

    peoplePicker.peoplePickerDelegate = self

    peoplePicker.displayedProperties = [NSNumber(value: kABPersonAddressProperty as Int32), NSNumber(value: kABPersonBirthdayProperty as Int32)]

    peoplePicker.predicateForSelectionOfPerson = NSPredicate(format: "postalAddresses.@count <= 1")

    peoplePicker.modalPresentationStyle = UIModalPresentationStyle.currentContext

    self.present(peoplePicker, animated: true, completion: nil)

...and here's the code with CNContactPickerViewController:

    let contactPicker = CNContactPickerViewController()

    contactPicker.delegate = self

    contactPicker.displayedPropertyKeys = [CNContactPostalAddressesKey, CNContactBirthdayKey]

    contactPicker.predicateForSelectionOfContact = NSPredicate(format: "postalAddresses.@count <= 1")

    contactPicker.modalPresentationStyle = UIModalPresentationStyle.currentContext

    self.present(contactPicker, animated: true, completion: nil)

So, to me, it looks like the same functionality is no longer available in the newer Contacts Framework, but I'm checking here to see if I missed something.


Solution

  • Note that there is no CNContact object returned. I get the CNPostalAddress in the contactProperty, but I don't receive the record of the owning contact.

    The CNContact object can be retrieved from the contact property of the CNContactProperty, so…

    However, when using CNContactPickerViewController, only this relevant delegate function is available:

    func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty)
    

    … implementing this delegate method would allow you to do what you want. But you want to make sure you're not implementing other delegate methods, such as:

    func contactPicker(CNContactPickerViewController, didSelect: CNContact)
    

    which will dismiss the picker the moment a contact (and not its property) is selected.