«Это приложение модифицирует механизм автомакета из фонового потока после того, как доступ к механизму был получен из основного потока» в Swift.

Я пытаюсь получить контакты пользователей. Все работает хорошо, за исключением того факта, что когда пользователь нажимает кнопку, чтобы разрешить нам доступ к контактам, контакты печатаются в консоли, но переход к другому контроллеру просмотра занимает много времени, и мой вывод в консоль идет как сумасшедший, говоря:

Это приложение модифицирует механизм автомакета из фонового потока после того, как доступ к механизму был получен из основного потока.

со списком стеков...

Прочитав об ошибке в StackOverflow, я обнаружил, что мне нужен DispatchQueue.main.async(). Однако я не могу понять, куда его положить? Может ли кто-нибудь объяснить это мне?

Это код выхода действия, когда кнопка нажата и где возникает ошибка:

@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
    }
}

person Matt Gilbert    schedule 06.02.2019    source источник


Ответы (1)


Весь код, относящийся к пользовательскому интерфейсу, должен выполняться в основном потоке. В вашем случае это переход

DispatchQueue.main.async { [weak self] in
    self?.performSegue(withIdentifier: "inviteFriends", sender: nil)
}
person mag_zbc    schedule 06.02.2019
comment
нет необходимости в [weak self] с GCD , это не вызывает циклов сохранения - person Sh_Khan; 06.02.2019
comment
Круто, спасибо за ответ. Однако я не хочу, чтобы PerformSegue выполнялся, если пользователь не разрешил доступ к контактам. Любая идея, как я могу решить эту проблему - person Matt Gilbert; 06.02.2019
comment
Верно, но я всегда пишу это по привычке - person mag_zbc; 06.02.2019
comment
@MattGilbert Поместите это в do { } после try - person mag_zbc; 06.02.2019
comment
Вы случайно не поместили его в блок завершения enumerateContacts? После try означает после закрывающей скобки блока завершения, после print(name) } - person mag_zbc; 06.02.2019
comment
О да .. ха-ха, мой плохой, спасибо за помощь, чувак! :) - person Matt Gilbert; 06.02.2019