Programmatically Link CNContacts

2019-03-21 23:54发布

问题:

In my app, I want to create a new contact. If a contact with the same name already exists, I want to link the new contact to the old one.

I have looked into the CNContact and CNContactStore references, and don't see any way to link contacts. Is this possible, and if so, how?

回答1:

In IOS9 contacts in different accounts that represent the same person may be automatically linked together.

To achieve this you should make sure that the name of your newly inserted contact matches the name of the contact you would like to unify with.

The documentation linked below gives the example of "John Appleseed" on iCloud and Facebook.

https://developer.apple.com/library/watchos/documentation/Contacts/Reference/Contacts_Framework/index.html



回答2:

Below is the code to merge a contact with the already present contact in contact store.Just an FYI that unique values like given name family name will be replaced and arrays such as numbers, emails, addresses will be appended with the existing values. Cheers!!

func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {
    picker.dismiss(animated: true, completion: nil)
    let identifier = contact.identifier
    updateContact(contactIdentifier: identifier)
}

func updateContact(contactIdentifier: String){

    let keysToFetch = [CNContactViewController.descriptorForRequiredKeys()]
    let contactStore = CNContactStore()
    do {
        let contactToUpdate =  try contactStore.unifiedContact(withIdentifier: contactIdentifier, keysToFetch: keysToFetch).mutableCopy() as! CNMutableContact
        if contactToUpdate.familyName.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
            contactToUpdate.familyName = "your value"
        }
        if contactToUpdate.givenName.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
            contactToUpdate.givenName = "your value"
        }
        if contactToUpdate.organizationName.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
            contactToUpdate.organizationName = "your value"
        }
        if contactToUpdate.jobTitle.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
            contactToUpdate.jobTitle = "your value"
        }
  // here the contact used below is the one that you want to merge with 
     an existing one.

        for i in contact.phoneNumbers {
            contactToUpdate.phoneNumbers.append(i)
        }
        for i in contact.emailAddresses {
            contactToUpdate.emailAddresses.append(i)
        }
        for i in contact.postalAddresses {
            contactToUpdate.postalAddresses.append(i)
        }
        let contactsViewController = CNContactViewController(forNewContact: contactToUpdate)
        contactsViewController.delegate = self
        contactsViewController.title = "Edit contact"
        contactsViewController.contactStore = contactStore
        let nav = UINavigationController(rootViewController: contactsViewController)
        DispatchQueue.main.async {
            self.present(nav, animated: true, completion: nil)
        }

    }
    catch {
        print(error.localizedDescription)
    }
}