Xcode UIView.init(frame :) должен использоваться только из основного потока
Я пытаюсь сделать некоторые представления в фоновом потоке, чтобы не влиять на основной поток. Это никогда не было проблемой перед Xcode 9.
DispatchQueue.global(qos: .background).async {
let customView = UIView(frame: .zero)
DispatchQueue.main.async {
self.view.addSubview(customView)
}
}
UIView.init(frame :) должен использоваться только из основного потока
Эта ошибка возникает во второй строке.
Обновить
Документация Apple UIView
самом деле говорит в разделе Threading Considerations:
Манипуляции к пользовательскому интерфейсу приложений должны присутствовать в основном потоке. Таким образом, вы всегда должны вызывать методы класса UIView из кода, запущенного в основном потоке вашего приложения. Единственный раз, когда это может быть не обязательно, необходимо при создании самого объекта вида, но все другие манипуляции должны происходить в основном потоке.
Ответы
Ответ 1
Xcode 9 имеет новую среду выполнения Main Thread Checker, которая обнаруживает вызов UIKit из фонового потока и генерирует предупреждения.
Я знаю, что он предназначен для создания предупреждений, а не для сбоя приложения, но вы можете попробовать отключить средство проверки основного потока для своей цели тестирования.
![enter image description here]()
Я попробовал этот код в примере проекта, отладчик остановился из-за проблемы (как и положено), но приложение не зависло.
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async {
let v = UIView(frame: .zero)
}
}
Ответ 2
Вы можете использовать эту функцию
func downloadImage(urlstr: String, imageView: UIImageView) {
let url = URL(string: urlstr)!
let task = URLSession.shared.dataTask(with: url) { data, _, _ in
guard let data = data else { return }
DispatchQueue.main.async { // Make sure you're on the main thread here
imageview.image = UIImage(data: data)
}
}
task.resume()
}
Как использовать эту функцию?
downloadImage(urlstr: "imageUrl", imageView: self.myImageView)
Ответ 3
Запись основного потока
Вы можете войти в основной поток следующим образом
DispatchQueue.main.async {
// UIView usage
}