skip to Main Content

When I use the Contacts Framework with Swift for iOS 15 using Xcode 13, when I use CNContactStore instance method unifiedContacts(matching:keysToFetch:), what happens to those CNContact objects that are not linked with any other CNContact objects, would they be returned as non-unified contacts, or would they be left out since they are non-unified contacts?

NOTE: I made an error in the original post before I fixed it. I meant to ask about unifiedContacts (with an "s").

Instead I accidentally wrote unifiedContact (without the "s").
The sample iOS Swift project ManagingContacts, uses both enumerateContacts(with:usingBlock:) and unifiedContacts(withIdentifier:keysToFetch:). Understanding why they choose to use each when they do may help answer the question.

The name "unifiedContacts" suggests it only fetches unified contacts, and does not fetch non-unified contacts that otherwise would meet the specified criteria, but it doesn’t make sense to me why there would ever be a need for it or why it is used in the said project when it is used.

From my test code, it looks like they both do the same thing. What do you think about this?

I tried this code in a test project:

class ViewController: UIViewController {

    let store = CNContactStore()
    
    let keys = [CNContactGivenNameKey as CNKeyDescriptor]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        store.requestAccess(for: .contacts) {
            
            permissionGranted, error in
            
            let request = CNContactFetchRequest(keysToFetch: self.keys)
            
            print("enumerate contacts")
            
            do {
                
                try self.store.enumerateContacts(with: request) {
                    
                    contact, pointer in
                    
                    print(contact.givenName)
                    
                }
            
            } catch {
                
                print("error")
                print(error.localizedDescription)
                
            }
            
            print("unified contacts")
            
            do {
                
                let containers = try self.store.containers(matching: nil)
            
                if containers.count > 1 {
                    fatalError("More than one container!")
                }
                
                let predicate = CNContact.predicateForContactsInContainer(withIdentifier: self.store.defaultContainerIdentifier())
                
                let contacts = try self.store.unifiedContacts(matching: predicate, keysToFetch: self.keys)

                for contact in contacts {
                    
                    print(contact.givenName)
                    
                }
                
            } catch {
                
                print("error")
                print(error.localizedDescription)

            }
                        
        }
        
    }


}

Here’s the result in the debug window:

enumerate contacts
Kate
Daniel
John
Anna
Hank
David
unified contacts
Kate
Daniel
John
Anna
Hank
David

2

Answers


  1. enumerateContacts will go over every contact that matches the fetch request that you pass to it. The block will be called once for each contact.

    unifiedContact is a function that receives the identifier of a contact and, if there are multiple cards for that contact, will give you a new contact that aggregates the values of all of those cards. If there is a single card then that’s what will be returned.

    You would probably run enumeracteContacts and then within the enumeration block you would call unifiedContact to make sure you get all the relevant values for that contact.

    Edit:

    In your updated question you’re actually using a different unifiedContact function than the one in your original question. This function returns an array of unified contacts.

    Your examples look the same because that is a basic address book and no contacts are linked. When you link two or more contacts you could have more than one contact card for a single contact, and unifiedContacts functions will return a single one with all the values.

    Login or Signup to reply.
  2. By default the Contacts framework returns unified contacts. You are absolutely right. The name "unifiedContacts" suggests it only fetches unified contacts, and does not fetch non-unified contacts… Other methods should be used to retrieve non-unified contacts.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search