Search code examples
swiftxcodedispatch-asynccncontact

“This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread” in Swift


Im trying to fetch a users contacts. Everything works well, except for the fact that when user clicks on button to allow us to access contacts, the contacts gets printed in console, but the segue to the other viewcontroller uses alot of time, and my console output is going like crazy saying:

This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread

with a list of stacks...

After reading about the error on StackOverflow, i found out i needed a DispatchQueue.main.async(). However i cant really get where to put it? Can someone explain it to me?

This is the code for the action outlet, when the button is pressed, and where the error occurs:

@IBAction func didTapFindContacts(_ sender: Any) {
    fetchContacts()
}

func fetchContacts() {
    contactStore.requestAccess(for: .contacts) { (success, error) in
        if let error = error {
            print("failed to request access:", error)
            return
        }

        if success {
            self.performSegue(withIdentifier: "inviteFriends", sender: nil)
            let contactStore = CNContactStore()
            let keys = [CNContactGivenNameKey,
                        CNContactPhoneNumbersKey,
                        CNContactFamilyNameKey] as [Any]
            let request = CNContactFetchRequest(keysToFetch: keys as! [CNKeyDescriptor])
            do {
                try contactStore.enumerateContacts(with: request){ (contact, stop) in
                    // Array containing all unified contacts from everywhere

                    let name = contact.givenName
                    let familyName = contact.familyName
                    let number = contact.phoneNumbers.first?.value.stringValue

                    let contactsAppend = ContactStruct(givenName: name, familyName: familyName, number: number!)
                    self.contacts.append(contactsAppend)

                    print(name)
            }
        } catch {
                print("unable to fetch contacts")
            }
        }
        //go to other page
    }
}

Solution

  • All code that relates to UI needs to run on main thread. In your case it's a segue

    DispatchQueue.main.async { [weak self] in
        self?.performSegue(withIdentifier: "inviteFriends", sender: nil)
    }