Pergunta

Em meu aplicativo baseado em documento, substituí o método openDocument:na minha subclasse de NSDocumentcontroller para que eu possa exibir meu próprio openPanel.Passo as URLs escolhidas para o método openDocumentWithContentsOfURL:display:completionHandler:.Eu uso este código para a chamada:

[self openDocumentWithContentsOfURL:[chosenFiles objectAtIndex:i] display:YES completionHandler:^(NSDocument *document, BOOL documentWasAlreadyOpen, NSError *error) {

    if (document == nil)
    {
        NSAlert* alert = [NSAlert alertWithError:error];
        [alert runModal];
    }

}];

Então, quero exibir o erro passado se nil for retornado como referência ao documento.O problema é que o programa simplesmente "congela" depois de pressionar o botão "Abrir" no painel aberto.Então preciso interromper manualmente o programa com o botão "parar" no Xcode.Nenhuma bola de praia giratória aparece, no entanto.Se eu comentar a linha "[alert runModal]", o programa não congela mais, mas nenhum alerta é exibido, é claro.

Agora o estranho:O código funciona às vezes.Se eu mudar do Xcode para o navegador e voltar e executar o programa novamente, às vezes ele funciona perfeitamente e o erro é exibido.Depois de algum tempo ele para de funcionar novamente.É imprevisível, mas na maioria das vezes não funciona.

Tudo isso me parece uma condição de corrida.Certamente tem algo a ver com o bloco?Mas o que eu faço de errado?

Foi útil?

Solução

Convertendo meu comentário em uma resposta:

runModel no thread principal.

[alert performSelectorOnMainThread:@selector(runModal) withObject:nil waitUntilDone:NO]; 

Acho que runModel precisa ser chamado no thread principal porque faz parte da estrutura do AppKit e está acionando essencialmente gráficos de UI.Acredito que todas as chamadas para o framework AppKit ou para qualquer método que manipule gráficos precisam estar no thread principal.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top