0

Most of the stuff I'm finding is using AddressBook instead of the new Contacts. I'm trying to get the names and phone numbers of all the user's contacts to display in a tableview on the app. Then take all those numbers into an API that cross references whether any of them already have accounts, so I can display an "add friend" button next to the ones that are. Is there a quick and easy way to ask for permission then get all the contacts into an array using Swift3 and compatible with iOS9 and newer?

I'm not trying to find or add a contact, I just want all the numbers and names in an array

Tommy K
  • 1,759
  • 3
  • 28
  • 51

1 Answers1

10

Two snippets below should help. I've double declared the store, which you wouldn't need to do if you use both snippets in the same scope...

To get permission:

    let store = CNContactStore()
    store.requestAccess(for: .contacts) { (isGranted, error) in
        // Check the isGranted flag and proceed if true
    }

To read the address book (I included some keys at random, but you can pick whatever is applicable to you.):

    let contactStore = CNContactStore()
    let keys = [CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactNicknameKey, CNContactPhoneNumbersKey]
    let request1 = CNContactFetchRequest(keysToFetch: keys  as [CNKeyDescriptor])

    try? contactStore.enumerateContacts(with: request1) { (contact, error) in
        for phone in contact.phoneNumbers {
            // Whatever you want to do with it
        }
    }
ghostatron
  • 2,620
  • 23
  • 27
  • 1
    Why are you catching an error when the closure itself will provide you with an error that you need to check? – Andy Ibanez Feb 13 '17 at 19:19
  • Oops! I copied that from my code and stripped out the extra trash. In my code, I am doing something that can throw in the closure but forgot to take the do/catch out. I will edit the answer. – ghostatron Feb 13 '17 at 19:21
  • that definitely helps! do you call the second snippet in some function or in `lazy var contacts: [CNContact] = { /* here */ }()` as seen in this http://stackoverflow.com/a/39066564/2868510 – Tommy K Feb 13 '17 at 21:17
  • That's up to you really. I'd put the 2nd snippet inside the closure for the first snippet so that permission is always checked before enumerating. Then, inside the enumerateContacts closure, populate the info you need into an array/dictionary/whatever that you can access elsewhere as needed. – ghostatron Feb 13 '17 at 22:08