Dicas sobre o ModalForWindow da NSApp, o ModalForWindow da NSAlert e o ModalSession [fechado]

Levei um pouco de experiência para esclarecer algumas confusões sobre a linguagem "ModalForWindow" do Objective-C e, posteriormente, como usar uma sessão modal. Talvez as dicas a seguir poupem tempo a alguém:

(Caso você seja novo no conceito: quando uma janela, geralmente um painel, é executada modal, isso impede que outra parte do aplicativo responda até que ele seja descartado.)

"ModalForWindow" significa coisas diferentes em diferentes circunstâncias. Se você estiver usando o loadNibNamed para exibir um painel definido por um xib e desejar que ele execute modal, chame-o assim que for exibido:

// Make panelReviewImports modal, so that no other part of app will respond.
[[NSApplication sharedApplication] runModalForWindow:self.panelReviewImports];

e acompanhe isso em seus métodos de demissão:

[[NSApplication sharedApplication] stopModal];

Mas para NSAlert, a "janela" em beginSheetModalForWindow refere-se à janela na qual o alerta seráem anexo como uma folha, qual janela será congelada até que o alerta seja descartado. Mas oaplicativo não será congelado; todas as outras janelas permanecerão operáveis. Se você deseja anexar um alerta como uma folha eAlém disso congele o restante do aplicativo, siga o código beginSheet com uma chamada simples para runModal e use o código de retorno explicitamente, assim:

[alert beginSheetModalForWindow:self.window 
                  modalDelegate:self didEndSelector:@selector(abandonmentAlertDidEnd:returnCode:contextInfo:) 
                    contextInfo:nil];
NSInteger returnCode = [alert runModal];
[self abandonmentAlertDidEnd:alert returnCode:returnCode contextInfo:nil];

(Obviamente, você implementou o código abandonmentAlertDidEnd: returnCode: contextInfo: como um método de classe.)

Ou, se você deseja que o alerta seja executado como um painel centralizado, chame runModal sozinho.

Suponha que você queira executar um modal de painel, seguido de um alerta se o usuário enviar uma entrada inválida. Você precisa parar o Modal antes de mostrar o alerta - após o qual, por algum motivo, outra chamada para executarModalForWindow falha ao funcionar corretamente. Para esse cenário, você precisa de umsessão modal:

1) Adicione uma propriedade NSModalSession à sua classe de controlador, porque o modalSession deve estar acessível em vários métodos.

2) Depois de exibir o painel, chame beginModalSessionForWindow para instanciar a modalSession:

self.modalSession = [[NSApplication sharedApplication] beginModalSessionForWindow:self.panelForInput];

3) Siga isso com um loop while que chama runModalSession, interrompendo quando seu retorno não for igual a NSRunContinuesResponse:

while ([[NSApplication sharedApplication] runModalSession:self.modalSession] == NSRunContinuesResponse)
    continue;

O loop será interrompido e o aplicativo será liberado quando o usuário clicar em um dos botões do painel. Digitar o campo de texto do painel deixará a sessão modal intacta.

4) No tratamento de botões, se a entrada do usuário for inválida, você chamará um alerta com runModal.

5) Imediatamente abaixo da chamada de alerta, no código que será executado assim que o alerta for descartado, você coloca o mesmo loop while usado acima. A sessão modal do painel é retomada.

6) Ao manipular o fechamento do painel, mediante entrada ou cancelamento válido, você chama endModalSession, o que, estranhamente, não é suficiente; você também deve chamar stopModal, mesmo que nunca tenha chamado runModalForWindow.

[[NSApplication sharedApplication] endModalSession:self.modalSession];
[[NSApplication sharedApplication] stopModal];
[self.panelForInput close];

questionAnswers(1)

yourAnswerToTheQuestion