0
func getContacts() {
    let store = CNContactStore()

    if CNContactStore.authorizationStatus(for: .contacts) == .notDetermined {
        store.requestAccess(for: .contacts, completionHandler: { (authorized: Bool, error: NSError?) -> Void in
            if authorized {
                self.retrieveContactsWithStore(store: store)
            }
        } as! (Bool, Error?) -> Void)
    } else if CNContactStore.authorizationStatus(for: .contacts) == .authorized {
        self.retrieveContactsWithStore(store: store)
    }
}

func retrieveContactsWithStore(store: CNContactStore) {
    do {
        let groups = try store.groups(matching: nil)
        let predicate = CNContact.predicateForContactsInGroup(withIdentifier: groups[0].identifier)
        //let predicate = CNContact.predicateForContactsMatchingName("John")
        let keysToFetch = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactEmailAddressesKey] as [Any]

        let contacts = try store.unifiedContacts(matching: predicate, keysToFetch: keysToFetch as! [CNKeyDescriptor])
        self.objects = contacts
        DispatchQueue.main.async(execute: { () -> Void in
            self.myTableView.reloadData()
        })
    } catch {
        print(error)
    }
}

I was trying to retrieve contacts from address book, but whenever I go to the view calling getContacts(), the app freezes. It wouldn't proceed anymore, but it didn't crash either. I wonder what went wrong here?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Chris Mikkelsen
  • 3,987
  • 9
  • 29
  • 41

1 Answers1

1

Your code for the call to requestAccess isn't correct. The syntax for the completion handler isn't valid. You need this:

func getContacts() {
    let store = CNContactStore()

    let status = CNContactStore.authorizationStatus(for: .contacts)
    if status == .notDetermined {
        store.requestAccess(for: .contacts, completionHandler: { (authorized: Bool, error: Error?) in
            if authorized {
                self.retrieveContactsWithStore(store: store)
            }
        })
    } else if status == .authorized {
        self.retrieveContactsWithStore(store: store)
    }
}

Also note the change to use the status variable. This is cleaner and easier to read than calling authorizationStatus over and over. Call it once and then check the value over and over as needed.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • this code has an error on else status == .authorized part, it says "fix it insert "," " – Chris Mikkelsen Dec 24 '16 at 00:09
  • Oops. I over edited. Add an `if` in there. See the update. – rmaddy Dec 24 '16 at 00:10
  • And one other typo - missed the closing parenthesis. – rmaddy Dec 24 '16 at 00:20
  • Dude what should I put in the parameter for this function? let predicate = CNContact.predicateForContactsInGroup(withIdentifier: ) – Chris Mikkelsen Dec 24 '16 at 00:44
  • That's a completely different question. If you can't find a solution after doing an appropriate amount of research (reading the documentation and searching), then please post a new question specific to your new issue. – rmaddy Dec 24 '16 at 00:48