Очень часто сталкивалась с этой ошибкой в моей ОС X с помощью быстрой:
"Это приложение изменяет механизм автозапуска из фонового потока, что может привести к повреждению двигателя и странным сбоям. Это приведет к исключению в будущей версии".
У меня есть мой NSWindow, и я обмениваюсь представлениями в contentView
окна. Я получаю ошибку при попытке сделать NSApp.beginSheet
в окне или когда я добавляю subview
к окну. Попробовал отключить функцию авторазрешения, и у меня нет ничего с помощью автоматического макета. Любые мысли?
Иногда это нормально, и ничего не происходит, в других случаях он полностью разбивает мой UI
и ничего не загружает
Хорошо - нашел ответ. Он должен быть помещен в другой поток, который позволяет обновлять пользовательский интерфейс, как только выполнение функции потока завершается:
DispatchQueue.main.async {
// Update UI
}
dispatch_async(dispatch_get_main_queue(){
// code here
})
dispatch_async(dispatch_get_main_queue(), ^{
// code here
});
Аналогичное сообщение об ошибке появляется при отладке с помощью операторов печати без использования "dispatch_async". Поэтому, когда вы получаете это сообщение об ошибке, время его использования
Swift 4
DispatchQueue.main.async { //code }
Swift 3
DispatchQueue.main.async(){ //code }
Предыдущие версии Swift
dispatch_async(dispatch_get_main_queue()){ //code }
dispatch_async(dispatch_get_main_queue(), ^{ /* UI related code */ });
Редактировать: я обновил его ответ, там лучше работает форматирование синтаксиса.
Используемый ответ @markussvensson для обнаружения моей проблемы нашел его с помощью этой символической точки останова:
[UIView layoutIfNeeded]
или [UIView updateConstraintsIfNeeded]
!(BOOL)[NSThread isMainThread]
movq 0x10880ba(%rip), %rsi ; "_wantsReapplicationOfAutoLayoutWithLayoutDirtyOnEntry:"
Когда вы пытаетесь обновить значение текстового поля или добавить подвью внутри фонового потока, вы можете получить эту проблему. По этой причине вы должны поместить этот вид кода в основной поток.
Вам нужно обернуть методы, которые вызывают обновления пользовательского интерфейса с dispatch_asynch, чтобы получить основную очередь. Например:
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.friendLabel.text = "You are following \(friendCount) accounts"
})
Теперь мы можем сделать это, следуя следующему коду:
// Move to a background thread to do some long running work
DispatchQueue.global(qos: .userInitiated).async {
// Do long running task here
// Bounce back to the main thread to update the UI
DispatchQueue.main.async {
self.friendLabel.text = "You are following \(friendCount) accounts"
}
}
У меня была эта проблема с момента обновления до IOS 9 SDK, когда я вызывал блок, который обновлял UI в обработчике завершения запроса асинхронного запроса NSURLConnection. Посылка вызова блока в dispatch_async с помощью dispatch_main_queue решила проблему.
Он отлично работал в iOS 8.
Для меня это сообщение об ошибке возникло из баннера из SDK Admob.
Мне удалось проследить происхождение до "WebThread", установив условную точку останова.
Затем я смог избавиться от проблемы, инкапсулируя создание баннера с помощью:
dispatch_async(dispatch_get_main_queue(), ^{
_bannerForTableFooter = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerPortrait];
...
}
Я не знаю, почему это помогло, поскольку я не вижу, как этот код вызывается из не основного потока.
Надеюсь, это может помочь кому угодно.
Была та же проблема, потому что я использовал performSelectorInBackground
.
Вы не должны изменять пользовательский интерфейс вне основного потока! UIKit не является потокобезопасным, так что проблема выше, а также некоторые другие странные проблемы возникнут, если вы это сделаете. Приложение может даже сбой.
Итак, чтобы выполнить операции UIKit, вам нужно определить блок и разрешить его выполнение в главной очереди: например,
NSOperationQueue.mainQueue().addOperationWithBlock {
}
Очевидно, что вы делаете обновление пользовательского интерфейса для обратной линии. Не могу предсказать, где именно, не видя своего кода.
Вот некоторые ситуации: -
вы можете что-то делать в фоновом потоке и не использовать. Будучи в той же функции, этот код легче определить.
DispatchQueue.main.async { // do UI update here }
вызов func, выполняющего вызов веб-запроса в фоновом потоке и его обработчик завершения, вызывающий другие функции, выполняющие обновление ui. для решения этой проблемы проверьте код, в котором вы обновили пользовательский интерфейс после вызова веб-запроса.
// Do something on background thread
DispatchQueue.global(qos: .userInitiated).async {
// update UI on main thread
DispatchQueue.main.async {
// Updating whole table view
self.myTableview.reloadData()
}
}
У меня была эта проблема при перезагрузке данных в UITableView. Просто отправьте перезагрузку следующим образом, исправив проблему для меня.
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
У вас уже есть правильный код ответа от @Mark, но, чтобы поделиться своими выводами: Проблема в том, что вы запрашиваете изменение в представлении и предполагаете, что это произойдет мгновенно. На самом деле загрузка представления зависит от доступных ресурсов. Если все загружается достаточно быстро и нет задержек, вы ничего не заметите. В сценариях, где есть какая-либо задержка из-за того, что поток процессов занят и т.д., Приложение запускается в ситуацию, когда предполагается, что оно отображает что-то, даже если оно еще не готово. Следовательно, желательно отправить эти запросы в асинхронных очередях, чтобы они выполнялись на основе нагрузки.
У меня была та же проблема. Оказывается, я использовал UIAlerts
, который нуждался в основной очереди. Но они устарели.
Когда я изменил UIAlerts
на UIAlertController
, у меня больше не было проблемы и не нужно было использовать какой-либо код dispatch_async
. Урок - обратите внимание на предупреждения. Они помогают, даже если вы этого не ожидаете.
У меня была такая же проблема при попытке обновить сообщение об ошибке в UILabel в том же ViewController (для обновления данных при попытке сделать это с обычным кодированием требуется некоторое время). Я использовал DispatchQueue
в Swift 3 Xcode 8, и он работает.
Это может быть нечто такое же простое, как установка текстового поля/метки или добавление подвью внутри фонового потока, что может привести к изменению макета поля. Убедитесь, что все, что вы делаете с интерфейсом, происходит только в основном потоке.
Проверьте эту ссылку: https://forums.developer.apple.com/thread/7399
У меня была эта проблема, когда я использовал TouchID, если это помогает кому-либо еще, обернуть вашу логику успеха, которая, вероятно, что-то сделает с пользовательским интерфейсом в основной очереди.
Swift 4,
Предположим, если вы вызываете некоторый метод, используя операционную очередь
operationQueue.addOperation({
self.searchFavourites()
})
И предположим, что функция searchFavourites похожа,
func searchFavourites() {
DispatchQueue.main.async {
//Your code
}
}
если вы вызываете, весь код внутри метода "searchFavourites" в основном потоке, он все равно будет давать ошибку, если вы обновляете в нем некоторый пользовательский интерфейс.
Это приложение модифицирует механизм автозапуска из фонового потока после того, как движок был доступен из основного потока.
Поэтому используйте решение,
operationQueue.addOperation({
DispatchQueue.main.async {
self.searchFavourites()
}
})
Для этого сценария.
Для меня проблема заключалась в следующем. Убедитесь, что performSegueWithIdentifier:
выполняется в основном потоке:
dispatch_async (dispatch_get_main_queue(), ^{
[self performSegueWithIdentifier:@"ViewController" sender:nil];
});
Я также столкнулся с этой проблемой, увидев тонну этих сообщений и трассировку стека на выходе, когда я изменил размер окна на меньший размер, чем его начальное значение. Проведя долгое время, выяснив проблему, я подумал, что поделюсь довольно простым решением. Я однажды включил возможность Can Draw Concurrently
на NSTextView
через IB. Это говорит AppKit, что он может вызывать метод draw(_:)
из другого потока. После его отключения у меня больше нет сообщений об ошибках. Я не испытывал никаких проблем до обновления до macOS 10.14 Beta, но в то же время я также начал изменять код для выполнения работы с текстовым представлением.