objective c - Consejos sobre ModalForWindow de NSApp, ModalForWindow de NSAlert y ModalSession
objective-c modal-dialog (1)
Me llevó un poco de experimentación aclarar un poco la confusión sobre el lenguaje "ModalForWindow" de Objective-C y, posteriormente, cómo usar una sesión modal. Tal vez los siguientes consejos le ahorren tiempo a alguien:
(En caso de que sea nuevo en el concepto: cuando una ventana, generalmente un panel, ejecuta modal, impide que otra parte de la aplicación responda hasta que se haya cerrado).
"ModalForWindow" significa diferentes cosas en diferentes circunstancias. Si está usando loadNibNamed para mostrar un panel definido por un xib y desea que se ejecute modal, llámelo una vez que se muestre:
// Make panelReviewImports modal, so that no other part of app will respond.
[[NSApplication sharedApplication] runModalForWindow:self.panelReviewImports];
Y seguir con esto en sus métodos de despido:
[[NSApplication sharedApplication] stopModal];
Pero para NSAlert, la "ventana" en beginSheetModalForWindow se refiere a la ventana a la que se adjuntará la alerta como una hoja, cuya ventana se congelará hasta que se descarte la alerta. Pero la aplicación no se congelará; Todas las demás ventanas permanecerán operables. Si desea adjuntar una alerta como una hoja y también congelar el resto de la aplicación, siga el código beginSheet con una simple llamada a runModal y use el código de retorno explícitamente, como este:
[alert beginSheetModalForWindow:self.window
modalDelegate:self didEndSelector:@selector(abandonmentAlertDidEnd:returnCode:contextInfo:)
contextInfo:nil];
NSInteger returnCode = [alert runModal];
[self abandonmentAlertDidEnd:alert returnCode:returnCode contextInfo:nil];
(Por supuesto, habrá implementado el abandonoAlertDidEnd: returnCode: contextInfo: code como un método de clase).
O, si desea que la alerta se ejecute como un panel centrado, llame a runModal por sí mismo.
Supongamos que desea ejecutar un panel modal, seguido de una alerta si el usuario envía una entrada no válida. Debería detener StopModal antes de mostrar la alerta; luego, por alguna razón, otra llamada a runModalForWindow no funciona correctamente. Para este escenario, necesitas una sesión modal :
1) Agregue una propiedad NSModalSession a su clase de controlador, ya que modalSession debe ser accesible a través de múltiples métodos.
2) Una vez que haya visualizado el panel, llame a beginModalSessionForWindow para crear una instancia de la modalSession:
self.modalSession = [[NSApplication sharedApplication] beginModalSessionForWindow:self.panelForInput];
3) Sigue esto con un bucle while que llama a runModalSession, rompiendo cuando su retorno no es igual a NSRunContinuesResponse:
while ([[NSApplication sharedApplication] runModalSession:self.modalSession] == NSRunContinuesResponse)
continue;
El bucle se interrumpirá y la aplicación se liberará cuando el usuario haga clic en uno de los botones del panel. (Si escribe en el campo de texto del panel, la sesión modal quedará intacta).
4) En su manejo de botones, si la entrada del usuario no es válida, llame a una alerta con runModal.
5) Inmediatamente debajo de la llamada de alerta, en el código que se ejecutará una vez que se descarte la alerta, coloque el mismo ciclo de tiempo usado arriba. La sesión modal del panel se reanuda.
6) En su manejo para cerrar el panel, ya sea mediante una entrada válida o una cancelación, llame a endModalSession, lo cual, curiosamente, no es suficiente; también debe llamar a stopModal, aunque nunca haya llamado a runModalForWindow.
[[NSApplication sharedApplication] endModalSession:self.modalSession];
[[NSApplication sharedApplication] stopModal];
[self.panelForInput close];
La pregunta es la respuesta. Solo estoy publicando esto para cerrarlo. Lo siento por torcer el formato de .