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 um meu NSWindow e estou trocando visualizações contentView
na janela. Eu recebo o erro quando tento fazer um NSApp.beginSheet
na janela ou quando adiciono um subview
na 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 a minha UI
e nada carrega
Respostas:
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 moderno:
Versões anteriores do Swift, antes do Swift 3.
Objetivo-C:
fonte
Você recebe uma mensagem de erro semelhante ao depurar com instruções de impressão sem usar 'dispatch_async'. Portanto, quando você recebe essa mensagem de erro, é hora de usar
Swift 4
Swift 3
Versões anteriores do Swift
fonte
dispatch_async(dispatch_get_main_queue(), ^{ /* UI related code */ });
Editar: atualizei sua resposta, a formatação da sintaxe funciona melhor lá.O erro "este aplicativo está modificando o mecanismo de execução 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):
[UIView layoutIfNeeded]
ou[UIView updateConstraintsIfNeeded]
!(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.
fonte
movq 0x10880ba(%rip), %rsi ; "_wantsReapplicationOfAutoLayoutWithLayoutDirtyOnEntry:"
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:
EDITADO - SWIFT 3:
Agora, podemos fazer isso seguindo o próximo código:
fonte
Para mim, essa mensagem de erro teve origem em 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:
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.
fonte
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.
fonte
Teve o mesmo problema porque eu estava usando
performSelectorInBackground
.fonte
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, você precisa definir o bloco e deixá-lo ser executado na fila principal: como,
fonte
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.
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.
fonte
O principal problema com "Este aplicativo está modificando o mecanismo de recuperação automática a partir de um encadeamento em segundo plano" é que ele parece estar registrado muito tempo após a ocorrência do problema real, dificultando a solução de problemas.
Consegui resolver o problema criando três pontos de interrupção simbólicos.
Depuração> Pontos de interrupção> Criar ponto de interrupção simbólico ...
Ponto de interrupção 1:
Símbolo:
-[UIView setNeedsLayout]
Doença:
!(BOOL)[NSThread isMainThread]
Ponto de interrupção 2:
Símbolo:
-[UIView layoutIfNeeded]
Doença:
!(BOOL)[NSThread isMainThread]
Ponto de interrupção 3:
Símbolo:
-[UIView updateConstraintsIfNeeded]
Doença:
!(BOOL)[NSThread isMainThread]
Com esses pontos de interrupção, você pode facilmente obter uma quebra na linha real em que chama incorretamente os métodos de interface do usuário no thread não principal.
fonte
Eu tive esse problema ao recarregar dados no UITableView. O simples envio do recarregamento da seguinte forma corrigiu o problema para mim.
fonte
Eu tive o mesmo problema. Acontece que eu estava usando o
UIAlerts
que precisava da fila principal. Mas eles foram preteridos .Quando mudei
UIAlerts
para paraUIAlertController
, não tinha mais o problema e não precisava usar nenhumdispatch_async
código. A lição - preste atenção aos avisos. Eles ajudam mesmo quando você não espera.fonte
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 assumindo que isso ocorrerá 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 deveria 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.
fonte
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.
fonte
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
fonte
Eu tive o mesmo problema ao tentar atualizar a mensagem de erro no UILabel no mesmo ViewController (demora um pouco para atualizar os dados ao tentar fazer isso com a codificação normal). Eu usei
DispatchQueue
no Swift 3 Xcode 8 e funciona.fonte
Se você deseja capturar esse erro, use a caixa de seleção principal do verificador de encadeamento em pausa. Corrigir é fácil na maioria das vezes, despachando a linha problemática na fila principal.
fonte
Para mim, a questão era a seguinte. Certifique-se de que
performSegueWithIdentifier:
é realizado no thread principal:fonte
Swift 4,
Suponha que, se você estiver chamando algum método usando a fila de operações
E suponha que a função searchFavourites seja como,
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.
Então use solução,
Para esse tipo de cenário.
fonte
Aqui, confira esta linha nos logs
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. Você precisa chamar sua função do thread principal dessa maneira.
Registra aqui
fonte
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 tinha ativado
Can Draw Concurrently
umNSTextView
através de IB. Isso informa ao AppKit que ele pode chamar odraw(_:)
método da visualização de outro thread. Depois de 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.fonte