App freezes when requesting access to addressbook

257 views Asked by At
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?

1

There are 1 answers

5
rmaddy On BEST ANSWER

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.