cocoa - Aclaración de comprensión de NSWindowController
cocoa-sheet (2)
¿Es este el caso incluso para la aplicación MainMenu.xib?
No, la semilla MainMenu es propiedad de NSApplication (es quién la carga).
¿Debería ser este también el caso del NSWC para la ventana MainMenu.xib, aunque esté abierto al inicio?
No, NSApplication carga el plumín principal en función de la propiedad "NSMainNibFile" del archivo de su aplicación. (Simplemente está preconfigurado en "MainMenu" en la plantilla de proyectos de Xcode). Si desea cambiar su nombre, cámbielo allí (y cambie el nombre de su archivo de punta). (Por cierto: esta propiedad también se puede cambiar en la vista "Resumen" de su objetivo en Xcode 4).
¿Debería el NSWC de la ventana MainMenu ser el delegado de la aplicación, o debería ser una clase diferente?
El propietario de la plumilla NSMainNibFile es la instancia de NSApplication que la carga y, por asociación, cualquier delegado de esa instancia. Ninguna de estas son subclases de NSWC.
En la misma línea, ¿debería el NSWC principal manejar los archivos (arrastrar / soltar y abrir), o debería pasarse al delegado de la aplicación, o es solo cuestión de gustos?
No hay un "NSWC principal" (la aplicación / delegado de la aplicación es el controlador del NSMainNibFile).
Todas las operaciones de arrastrar y soltar son manejadas por las subclases NSWindow o NSView. Usualmente uso una subclase NSWindow o NSView especial que pasa todos los métodos de arrastrar y soltar al delegado. Por ejemplo:
- (unsigned int) draggingEntered:sender
{
return [[self delegate] draggingEntered:sender];
}
De esta forma puedo mantener todos mis códigos de ventana / vista juntos en sus respectivos controladores (según lo determine su propietario de plumillas). Y debido a que el código específico de la ventana / vista está en el controlador (no en la subclase NSWindow / NSView), todos los tipos de NSWindows / NSViews pueden usar las mismas subclases de arrastrar y soltar.
He usado NSWindowController en proyectos varias veces, y siento que tengo una comprensión (muy) aproximada de los conceptos detrás de esta importante clase. Lo que me gustaría hacer con esta publicación es aclarar / corregir mis propios entendimientos y, con suerte, ayudar a otros alumnos a obtener el primer paso para comprender. Son los conceptos, la visión general y las mejores prácticas de un vistazo que considero que son más útiles y que a menudo faltan en la documentación. Aquí está mi opinión sobre NSWindowController (las preguntas están intercaladas en negrita):
- Existe una subclase NSWindowController (NSWC) (conceptualmente) justo debajo de cada fila de ventana, que actúa como el pegamento entre los elementos de la interfaz de usuario y los objetos de modelo que controlan / representan. Básicamente, cada ventana en su aplicación debe tener su propia subclase NSWC.
- El propietario del archivo de la punta siempre debe ser la subclase NSWC. ¿Es este el caso incluso para la aplicación MainMenu.xib?
- La propiedad de
window
NSWC siempre debe estar vinculada a NSWindow en InterfaceBuilder. - Debe anular el método ''init'', utilizando
[super initWithWindowNibName:]
, de modo que cuando se refiera a[mycontroller window]
cargará el plumín. ¿Debería ser este también el caso del NSWC para la ventana MainMenu.xib, aunque esté abierto al inicio? - El NSWC no debe hacer demasiado trabajo pesado, simplemente debe pasar mensajes a instancias de objetos y presentarlos en la interfaz de usuario.
- Puede modificar la UI mediante el enlace, o actuar como delegado para tablas, etc., o al cambiar activamente los elementos de la UI cuando observa un cambio, o una combinación de cualquiera de los anteriores (cuál de ellos usa parece ser una cuestión de gusto, con ventajas y desventajas en todos los lados).
- Un NSWC puede crear instancias de otros NSWC cuando sea necesario (por ejemplo, al abrir una subventana única).
Use el
[mycontroller showWindow:nil]
para mostrar la ventana asociada al frente. Si desea que la ventana aparezca como una hoja, use algo como:NSWindowController* mycontroller = [[MyController alloc] init]; [NSApp beginSheet: [mycontroller window] modalForWindow: [self window] modalDelegate: self didEndSelector: @selector(didEndMySheet:returnCode:contextInfo:) contextInfo: nil];
El didEndSelector:
debe ser un método del NSWC de la ventana principal, y puede acceder y liberar ''mycontroller'' con [sheet windowController]
. - Para cerrar la ventana, llame al método performClose:
de la ventana de NSWC.
Algunas preguntas:
- ¿Debería el NSWC de la ventana MainMenu ser el delegado de la aplicación, o debería ser una clase diferente?
- En la misma línea, ¿debería el NSWC principal manejar los archivos (arrastrar / soltar y abrir), o debería pasarse al delegado de la aplicación, o es solo cuestión de gustos?
Por favor corrígeme si algo de esto es una mala práctica, o simplemente está mal. Estoy buscando aclarar mi comprensión de NSWindowController, por lo que cualquier adición (en forma de mejores prácticas, experiencias, errores) sería muy apreciada.
Gracias, Laurie
¿Para qué sirven los controladores de ventana?
Los controladores de ventana son herramientas para cargar una ventana desde un archivo NIB y para administrar la memoria de los recursos asignados en el NIB. Antes, allí donde NSWindowControllers
básicamente tenía que escribir el mismo código para cada ventana o inventar una clase de controlador de ventana propia.
Por supuesto, también son controladores en el sentido Modelo / Vista / Controlador, por lo que son el lugar correcto para conectar las vistas desde la ventana a los objetos modelo. Para hacer esto, a menudo necesitan actuar como el delegado o la fuente de datos para un objeto de vista. Entonces obtuviste esta parte perfectamente bien.
También los controladores de ventana son una herramienta para la reutilización de código. Hace que sea fácil soltar la clase de controlador de ventana y es XIB / NIB en otro proyecto y usarlo allí.
Entonces sí, cada ventana de un NIB debe ser propiedad de un controlador de ventana, con una excepción. En realidad, esto es solo una guía para un buen código, nada lo hace cumplir.
WindowControllers y MainMenu.xib
MainMenu.xib
es una cosa diferente, allí no puedes usar un controlador de ventana. Este NIB es cargado por NSApplication
por lo que tiene que ser su "Propietario de archivos". No hay forma de obtener un controlador de ventana entre NSApplication
y NIB. Tampoco es necesario utilizar un controlador de ventana para la gestión de memoria allí, ya que el objeto de aplicación vive durante todo el tiempo de ejecución del programa, por lo que no tiene que limpiar sus recursos del NIB cuando se desasigna.
Si realmente necesita un controlador de ventana para su ventana principal, no puede poner esto en MainMenu.xib
.
Espero que esto ayude. Probablemente hay mucho más que decir sobre los controladores de ventanas también