swiftcontacts

Reading values for CNContact InstantMessageAddressesKey


I am trying to work with all contacts on my iPhone who have a specific code which is stored in the Instant Message field of the contacts.

The code for fetching:

func fetchAllContacts() async {
    // Get access to the Contacts Store
    let store = CNContactStore()
    // Specify which data keys we ant to fetch
    let keys = [CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactInstantMessageAddressesKey] as [CNKeyDescriptor]
    // Create an fetch request
    let fetchRequest = CNContactFetchRequest(keysToFetch: keys)
    // Call method to fetch all contacts
    do {
        try store.enumerateContacts(with: fetchRequest, usingBlock: { contact, result in
        
            if !contact.instantMessageAddresses.isEmpty  {
                print(contact.givenName)
                print(contact.instantMessageAddresses)
            }
        })
    }
    catch {
        print("Error")
    }
}

It works fine and the following contact information is printed to the console:

Roman
[<CNLabeledValue: 0x282783100: identifier=0E327523-281C-49D7-A4A1-7E5FF9F10F1C, label=(nil), value=<CNMutableInstantMessageAddress: 0x283ccdda0: username=01 1244 131 01, userIdentifier=(nil), service=, teamIdentifier=(nil), bundleIdentifiers=(nil)>, iOSLegacyIdentifier=0>]

How can I get the username string? I need this string "01 1244 131 01" and I don't know how to read this string in a variable.

I tried the following, but it throws an error:

print ("C-Value: \(contact.value(forKey: "username")!)")

Solution

  • As you can see from the documentation for instantMessageAddresses:

    This property is an array of CNLabeledValue objects, each of which has a label and a CNInstantMessageAddress value.

    Instead of print(contact.instantMessageAddresses) you could use the following to print the first address (if any):

    print(contact.instantMessageAddresses.first?.value.username)
    

    Of course if the contact has more than one instant message address you will need to iterate through the array and access all of them.

    This will create an array of usernames (containing 0 or more results):

    let usernames = contact.instantMessageAddresses.map { $0.value.username }