iosswiftxcodecontactscncontactstore

Does unifiedContacts(matching:keysToFetch:) return only unified contacts and leave out non-unified contacts?


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

Solution

  • 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.