на дисплее UIAlert произойдет сбой приложения? - PullRequest
2 голосов
/ 06 ноября 2019

У меня есть логика действия тестового соединения. он будет тестировать сервер в живую или нет. ошибка возникает, когда логика завершает тест и пытается отобразить UIAlertController внутри потока закрытия, это приведет к сбою системы.

@IBAction func TestNetwork(_ sender: Any) {
    var message = "\(internetConnection) internet connection \n \(serverStatus) server\n  "
    self.showSpinner(onView: self.view)
    DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
        self.testConnection(connectionTestCompletionHanlder: {connectionResult in


            let alertController = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
            let defaultAction = UIAlertAction(title: "OK", style: .default) { (action) in
                // Respond to user selection of the action.
            }
            alertController.addAction(defaultAction)
            //self.removeSpinner()
            self.present(alertController, animated: true){
                // The alert was presented
            }
        })
    }
}

ошибка

- [Assert] Невозможно вызвать с помощью asCopy= НЕТ на неосновной теме. + [UIView setAnimationsEnabled:] вызывается из фонового потока. Выполнение любой операции из фонового потока в UIView или подклассе не поддерживается и может привести к неожиданному и коварному поведению.
-Не поддерживается использование интерфейса настройки представления UIKit вне основного потока. -setHasDimmingView: отправлено в <_UIAlertControllerView: 0x7ffe2ff8b4a0;кадр = (0 0; 375 667);layer =>

-Запускающее приложение из-за необработанного исключения «NSInternalInconsistencyException», причина: «Модификации механизма компоновки не должны выполняться из фонового потока после того, как к нему был получен доступ из основного потока. '

1 Ответ

3 голосов
/ 06 ноября 2019

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

//previous code as above...

DispatchQueue.main.async {
  self.present(alertController, animated: true){
    // The alert was present
  }
}

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

...