Вопрос:

Появляется сообщение об ошибке «Это приложение модифицирует механизм автоматической разметки из фонового потока»?

swift macos autolayout background-thread

135205 просмотра

19 ответа

8538 Репутация автора

Я часто сталкивался с этой ошибкой в ​​моей OS X, используя swift:

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

У меня есть мое NSWindow, и я меняюсь в представлении contentViewокна. Я получаю сообщение об ошибке, когда пытаюсь сделать NSApp.beginSheetокно или добавить его subviewв окно. Пробовал отключать авторазмер, а у меня ничего не получается с помощью авторазметки. Какие-нибудь мысли?

Иногда это нормально и ничего не происходит, иногда это полностью ломает меня UIи ничего не загружается

Автор: Mark Источник Размещён: 03.02.2015 03:01

Ответы (19)


613 плюса

8538 Репутация автора

Решение

Ладно - нашел ответ. Он должен быть помещен в другой поток, который позволяет обновлять пользовательский интерфейс после завершения выполнения функции потока:

Свифт 3

 DispatchQueue.main.async {
    // Update UI
 }

Swift Version <3

dispatch_async(dispatch_get_main_queue(){
    // code here
})

Версия Objective-C

dispatch_async(dispatch_get_main_queue(), ^{
    // code here
});
Автор: Mark Размещён: 04.02.2015 12:19

10 плюса

3981 Репутация автора

Была такая же проблема, потому что я использовал performSelectorInBackground.

Автор: Bobby Размещён: 25.07.2015 07:01

19 плюса

823 Репутация автора

У меня была эта проблема с момента обновления до iOS 9 SDK, когда я вызывал блок, который делал обновления пользовательского интерфейса в обработчике завершения асинхронного запроса NSURLConnection. Помещение вызова блока в dispatch_async с использованием dispatch_main_queue решило проблему.

Это работало нормально в iOS 8.

Автор: spongessuck Размещён: 21.09.2015 06:33

2 плюса

958 Репутация автора

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

Автор: Stuart P. Размещён: 30.10.2015 09:59

143 плюса

6795 Репутация автора

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

Swift 4

DispatchQueue.main.async { //code }

Свифт 3

DispatchQueue.main.async(){ //code }

Ранние версии Swift

dispatch_async(dispatch_get_main_queue()){ //code }
Автор: Naishta Размещён: 30.11.2015 10:03

25 плюса

758 Репутация автора

При попытке обновить значение текстового поля или добавить подпредставление в фоновом потоке, вы можете получить эту проблему. По этой причине вы должны поместить этот вид кода в основной поток.

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

dispatch_async(dispatch_get_main_queue(), { () -> Void in
   self.friendLabel.text = "You are following \(friendCount) accounts"
})

РЕДАКТИРОВАНИЕ - SWIFT 3:

Теперь мы можем сделать это, следуя следующему коду:

// 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"
   }
}
Автор: Jorge Luis Jiménez Размещён: 17.12.2015 01:16

3 плюса

71 Репутация автора

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

Автор: epaus Размещён: 27.01.2016 05:47

7 плюса

751 Репутация автора

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

Итак, чтобы выполнить операции UIKit, вам нужно определить блок и позволить ему выполняться в главной очереди: например,

NSOperationQueue.mainQueue().addOperationWithBlock {

}
Автор: Chowdhury Md Rajib Sarwar Размещён: 05.02.2016 03:25

2 плюса

1384 Репутация автора

Это может быть что-то столь же простое, как установка значения текстового поля / метки или добавление подпредставления внутри фонового потока, что может привести к изменению макета поля. Убедитесь, что все, что вы делаете с интерфейсом, происходит только в основном потоке.

Проверьте эту ссылку: https://forums.developer.apple.com/thread/7399

Автор: Kiran P Nair Размещён: 23.04.2016 06:03

21 плюса

1097 Репутация автора

Для меня это сообщение об ошибке возникло из баннера от Admob SDK.

Я смог отследить источник до «WebThread», установив условную точку останова.

условная точка останова, чтобы найти, кто обновляет пользовательский интерфейс из фонового потока

Тогда я смог избавиться от этой проблемы, заключив в капсулу создание баннера:

dispatch_async(dispatch_get_main_queue(), ^{
   _bannerForTableFooter = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerPortrait];
   ...
}

Я не знаю, почему это помогло, так как я не могу понять, как этот код вызывался из не основного потока.

Надеюсь, это может кому-нибудь помочь.

Автор: markussvensson Размещён: 24.05.2016 06:47

3 плюса

432 Репутация автора

У вас уже есть правильный код ответа от @Mark, но просто для того, чтобы поделиться моими выводами: Проблема в том, что вы запрашиваете изменение представления и предполагаете, что это произойдет мгновенно. На самом деле загрузка представления зависит от доступных ресурсов. Если все загружается достаточно быстро и задержек нет, вы ничего не замечаете. В сценариях, где есть какая-либо задержка из-за занятости потока процесса и т. Д., Приложение сталкивается с ситуацией, когда оно должно что-то отображать, даже если оно еще не готово. Следовательно, желательно отправлять эти запросы в асинхронных очередях, чтобы они выполнялись в зависимости от нагрузки.

Автор: Mukund Agarwal Размещён: 07.08.2016 08:27

4 плюса

46 Репутация автора

У меня была эта проблема при перезагрузке данных в UITableView. Простая отправка перезагрузки, как это было решено для меня.

    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.tableView.reloadData()
    })
Автор: ReshDev Размещён: 15.09.2016 06:43

70 плюса

8692 Репутация автора

Ошибка «это приложение модифицирует механизм автоматической разметки из фонового потока» регистрируется в консоли задолго до того, как возникла реальная проблема, поэтому отладка может быть сложной без использования точки останова.

Я использовал ответ @ markussvensson, чтобы обнаружить мою проблему и нашел ее, используя эту символическую точку останова (Debug> Breakpoints> Create Symbolic Breakpoint):

  1. Символы: [UIView layoutIfNeeded]или[UIView updateConstraintsIfNeeded]
  2. Состояние: !(BOOL)[NSThread isMainThread]

введите описание изображения здесь

Создайте и запустите приложение на эмуляторе и скопируйте шаги, которые приводят к выдаче сообщения об ошибке (приложение будет работать медленнее, чем обычно!). Затем Xcode остановит приложение и отметит строку кода (например, вызов функции), которая обращается к пользовательскому интерфейсу из фонового потока.

Автор: k06a Размещён: 26.09.2016 09:39

2 плюса

141 Репутация автора

У меня возникла та же проблема при попытке обновить сообщение об ошибке в UILabel в том же ViewController (для обновления данных требуется некоторое время при попытке сделать это с помощью обычного кодирования). Я использовал DispatchQueueв Swift 3 Xcode 8, и это работает.

Автор: FN90 Размещён: 04.10.2016 05:47

6 плюса

1201 Репутация автора

Очевидно, что вы делаете некоторое обновление пользовательского интерфейса в фоновом потоке. Не могу предсказать, где именно, не видя ваш код.

Вот некоторые ситуации, которые могут произойти:

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

DispatchQueue.main.async { // do UI update here }

Вызов функции, выполняющей вызов веб-запроса в фоновом потоке, и обработчик ее завершения. Вызов другой функции, выполняющей обновление пользовательского интерфейса. Чтобы решить эту проблему, попробуйте проверить код, в котором вы обновили пользовательский интерфейс после вызова веб-запроса.

// 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()
            }
}
Автор: Ashish Pisey Размещён: 27.06.2017 07:19

1 плюс

231 Репутация автора

Для меня проблема заключалась в следующем. Убедитесь, что performSegueWithIdentifier:выполняется в основном потоке:

dispatch_async (dispatch_get_main_queue(), ^{
  [self performSegueWithIdentifier:@"ViewController" sender:nil];
});
Автор: Offek Размещён: 25.05.2018 11:16

1 плюс

674 Репутация автора

Swift 4,

Предположим, если вы вызываете какой-либо метод, используя очередь операций

operationQueue.addOperation({
            self.searchFavourites()
        })

И предположим, что функция searchFavourites похожа,

func searchFavourites() {
     DispatchQueue.main.async {
                    //Your code
                }
}

если вы вызываете весь код внутри метода "searchFavourites" в главном потоке, он все равно выдаст ошибку, если вы обновите в нем какой-либо пользовательский интерфейс.

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

Так что используйте решение,

operationQueue.addOperation({
            DispatchQueue.main.async {
                self.searchFavourites()
            }
        })

Для такого сценария.

Автор: Pramod More Размещён: 28.05.2018 01:16

0 плюса

498 Репутация автора

Я также столкнулся с этой проблемой, увидев тонну этих сообщений и следов стека, напечатанных на выходе, когда я изменил размер окна до меньшего размера, чем его первоначальное значение. Потратив долгое время на выяснение проблемы, я решил поделиться довольно простым решением. Я когда-то включил Can Draw Concurrentlyна NSTextViewсквозной IB. Это говорит AppKit, что он может вызывать draw(_:)метод представления из другого потока. После его отключения я больше не получаю никаких сообщений об ошибках. У меня не возникало никаких проблем до обновления до MacOS 10.14 Beta, но в то же время я также начал изменять код для работы с текстовым представлением.

Автор: Andreas Размещён: 02.08.2018 10:28

2 плюса

5245 Репутация автора

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

введите описание изображения здесь

Автор: rockdaswift Размещён: 14.01.2019 12:12
Вопросы из категории :
32x32