swift - Obtendo um erro "Este aplicativo está modificando o mecanismo de execução automática a partir de um thread em segundo plano"?




macos autolayout (14)

Ao tentar atualizar um valor do campo de texto ou adicionar uma subvisão dentro de um encadeamento em segundo plano, você pode obter esse problema. Por esse motivo, você deve colocar esse tipo de código no thread principal.

Você precisa agrupar métodos que chamam atualizações da interface do usuário com dispatch_asynch para obter a fila principal. Por exemplo:

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

EDITADO - SWIFT 3:

Agora, podemos fazer isso seguindo o próximo código:

// 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"
   }
}

Venho encontrando muito esse erro no meu OS X usando o swift:

"Este aplicativo está modificando o mecanismo de execução automática a partir de um encadeamento em segundo plano, o que pode levar à corrupção do mecanismo e falhas estranhas. Isso causará uma exceção em uma versão futura."

Eu tenho meu NSWindow e estou trocando visualizações para o contentView da janela. Eu recebo o erro quando tento NSApp.beginSheet um NSApp.beginSheet na janela ou quando adiciono uma subview à janela. Tentei desativar o material de redimensionamento automático e não tenho nada usando o layout automático. Alguma ideia?

Às vezes está tudo bem e nada acontece, outras vezes quebra totalmente minha UI e nada carrega


Aqui, confira esta linha nos logs

 $S12AppName18ViewControllerC11Func()ySS_S2StF + 4420 

você pode verificar qual a função que está chamando do thread de segundo plano ou para onde você está chamando o método API, precisa chamar sua função do thread principal dessa maneira.

 DispatchQueue.main.async { func()} 

func () é a função que você deseja chamar no resultado do sucesso da chamada da API ou então.

Registra aqui

 This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes. Stack:( 0 Foundation 0x00000001c570ce50 <redacted> + 96 1 Foundation 0x00000001c5501868 <redacted> + 32 2 Foundation 0x00000001c5544370 <redacted> + 540 3 Foundation 0x00000001c5543840 <redacted> + 396 4 Foundation 0x00000001c554358c <redacted> + 272 5 Foundation 0x00000001c5542e10 <redacted> + 264 6 UIKitCore 0x00000001f20d62e4 <redacted> + 488 7 UIKitCore 0x00000001f20d67b0 <redacted> + 36 8 UIKitCore 0x00000001f20d6eb0 <redacted> + 84 9 Foundation 0x00000001c571d124 <redacted> + 76 10 Foundation 0x00000001c54ff30c <redacted> + 108 11 Foundation 0x00000001c54fe304 <redacted> + 328 12 UIKitCore 0x00000001f151dc0c <redacted> + 156 13 UIKitCore 0x00000001f151e0c0 <redacted> + 152 14 UIKitCore 0x00000001f1514834 <redacted> + 868 15 UIKitCore 0x00000001f1518760 <redacted> + 104 16 UIKitCore 0x00000001f1543370 <redacted> + 1772 17 UIKitCore 0x00000001f1546598 <redacted> + 120 18 UIKitCore 0x00000001f14fc850 <redacted> + 1452 19 UIKitCore 0x00000001f168f318 <redacted> + 196 20 UIKitCore 0x00000001f168d330 <redacted> + 144 21 AppName 0x0000000100b8ed00 $S12AppName18ViewControllerC11Func()ySS_S2StF + 4420 22 AppName 0x0000000100b8d9f4 $S12CcfU0_y10Foundation4DataVSg_So13NSURLResponseCSgs5Error_pSgtcfU_ + 2384 23 App NAme 0x0000000100a98f3c $S10Foundation4DataVSgSo13NSURLResponseCSgs5Error_pSgIegggg_So6NSDataCSgAGSo7NSErrorCSgIeyByyy_TR + 316 24 CFNetwork 0x00000001c513aa00 <redacted> + 32 25 CFNetwork 0x00000001c514f1a0 <redacted> + 176 26 Foundation 0x00000001c55ed8bc <redacted> + 16 27 Foundation 0x00000001c54f5ab8 <redacted> + 72 28 Foundation 0x00000001c54f4f8c <redacted> + 740 29 Foundation 0x00000001c55ef790 <redacted> + 272 30 libdispatch.dylib 0x000000010286f824 _dispatch_call_block_and_release + 24 31 libdispatch.dylib 0x0000000102870dc8 _dispatch_client_callout + 16 32 libdispatch.dylib 0x00000001028741c4 _dispatch_continuation_pop + 528 33 libdispatch.dylib 0x0000000102873604 _dispatch_async_redirect_invoke + 632 34 libdispatch.dylib 0x00000001028821dc _dispatch_root_queue_drain + 376 35 libdispatch.dylib 0x0000000102882bc8 _dispatch_worker_thread2 + 156 36 libsystem_pthread.dylib 0x00000001c477917c _pthread_wqthread + 472 37 libsystem_pthread.dylib 0x00000001c477bcec start_wqthread + 4 ) 

Eu tive esse problema desde a atualização para o iOS 9 SDK quando estava chamando um bloco que fazia atualizações da interface do usuário em um manipulador de conclusão de solicitação assíncrona NSURLConnection. A colocação da chamada de bloco em um dispatch_async usando o dispatch_main_queue resolveu o problema.

Funcionou bem no iOS 8.


Eu tive esse problema quando estava usando o TouchID, se isso ajudar alguém, quebra sua lógica de sucesso, o que provavelmente faz algo com a interface do usuário na fila principal.


Eu tive o mesmo problema. Acontece que eu estava usando UIAlerts que precisava da fila principal. Mas eles foram preteridos .
Quando mudei o UIAlerts para o UIAlertController , não tive mais o problema e não precisei usar nenhum código dispatch_async . A lição - preste atenção aos avisos. Eles ajudam mesmo quando você não espera.


O erro "este aplicativo está modificando o mecanismo de saída automática a partir de um encadeamento em segundo plano" é registrado no console muito tempo após o problema real, portanto, a depuração pode ser difícil sem o uso de um ponto de interrupção.

Usei a resposta de @ markussvensson para detectar meu problema e o encontrei usando este ponto de interrupção simbólico (Depuração> Pontos de interrupção> Criar ponto de interrupção simbólico):

  1. Símbolos: [UIView layoutIfNeeded] ou [UIView updateConstraintsIfNeeded]
  2. Condição !(BOOL)[NSThread isMainThread]

Crie e execute o aplicativo no emulador e replique as etapas que levam à exibição da mensagem de erro (o aplicativo será mais lento que o normal!). O Xcode irá parar o aplicativo e marcar a linha de código (por exemplo, a chamada de uma função) que está acessando a interface do usuário a partir de um encadeamento em segundo plano.


Obviamente, você está fazendo alguma atualização da interface do usuário no encadeamento de back ground. Não é possível prever exatamente onde, sem ver seu código.

Estas são algumas situações que podem acontecer: -

você pode estar fazendo algo no thread de segundo plano e não usando. Estando na mesma função, esse código é mais fácil de detectar.

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

chamando um func fazendo chamada de solicitação da web no thread de segundo plano e seu manipulador de conclusão chamando outro func fazendo atualização da interface do usuário. para resolver isso, tente verificar o código em que você atualizou a interface do usuário após a chamada de solicitação da web.

// 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()
            }
}

Ok - encontrei a resposta. Ele precisa ser colocado dentro de um thread diferente que permita que a interface do usuário seja atualizada assim que a execução da função do thread for concluída:

Swift 3

 DispatchQueue.main.async {
    // Update UI
 }

Versão rápida <3

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

Versão Objective-C

dispatch_async(dispatch_get_main_queue(), ^{
    // code here
});

Para mim, essa mensagem de erro se originou de um banner do Admob SDK.

Consegui rastrear a origem para "WebThread" definindo um ponto de interrupção condicional.

Consegui me livrar do problema encapsulando a criação do banner com:

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

Não sei por que isso ajudou, pois não consigo ver como esse código foi chamado a partir de um thread não principal.

Espero que possa ajudar alguém.


Pode ser algo tão simples quanto definir um valor de campo / rótulo de texto ou adicionar uma subvisão dentro de um encadeamento em segundo plano, o que pode causar alterações no layout de um campo. Certifique-se de que qualquer coisa que você faça com a interface ocorra apenas no thread principal.

Verifique este link: https://forums.developer.apple.com/thread/7399


Swift 4,

Suponha que, se você estiver chamando algum método usando a fila de operações

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

E suponha que a função searchFavourites seja como,

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

se você chamar todo o código dentro do método "searchFavourites" no thread principal, ele ainda causará um erro se você estiver atualizando alguma interface do usuário.

Este aplicativo está modificando o mecanismo de autolayout a partir de um encadeamento em segundo plano depois que o mecanismo foi acessado no encadeamento principal.

Então use solução,

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

Para esse tipo de cenário.


Também encontrei esse problema, vendo uma tonelada dessas mensagens e rastreamentos de pilha sendo impressos na saída, quando redimensionei a janela para um tamanho menor que o valor inicial. Passando muito tempo descobrindo o problema, pensei em compartilhar a solução bastante simples. Uma vez eu havia habilitado o Can Draw Concurrently NSTextView em um NSTextView por meio do IB. Isso informa ao AppKit que ele pode chamar o método draw(_:) da visualização de outro thread. Após desativá-lo, não recebi mais nenhuma mensagem de erro. Não tive problemas antes de atualizar para o macOS 10.14 Beta, mas, ao mesmo tempo, também comecei a modificar o código para executar o trabalho com a exibição de texto.


Você já tem a resposta de código correta do @Mark, mas apenas para compartilhar minhas descobertas: O problema é que você está solicitando uma alteração na exibição e presumindo que isso ocorra instantaneamente. Na realidade, o carregamento de uma visualização depende dos recursos disponíveis. Se tudo carregar rápido o suficiente e não houver atrasos, você não perceberá nada. Em cenários em que existe algum atraso devido ao processo estar ocupado, etc, o aplicativo se depara com uma situação em que ele deve exibir algo mesmo que ainda não esteja pronto. Portanto, é aconselhável despachar essas solicitações em filas assíncronas para que elas sejam executadas com base na carga.


Você não deve alterar a interface do usuário fora do segmento principal! O UIKit não é seguro para threads, de modo que o problema acima e também outros problemas estranhos surgirão se você fizer isso. O aplicativo pode até falhar.

Portanto, para executar as operações do UIKit, é necessário definir o bloco e permitir que ele seja executado na fila principal: como,

NSOperationQueue.mainQueue().addOperationWithBlock {

}




background-thread