2012-01-18 617 views
9

Estoy trabajando en mi primera aplicación Mac basada en documentos.NSDocumentController currentDocument return nil

He subclase NSDocument, reimplementar métodos tales como

- (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError; 
- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError; 
- (void)makeWindowControllers; 

El controlador principal ventana es una subclase de NSWindowsController, que contiene dos NSViewController subclases.

El problema al que me enfrento es que necesito tener acceso al documento actual desde estos controladores de vista. Lo que hago es llamar

MyDocument *myDocument = [[NSDocumentController sharedController] currentDocument]; 

Al principio, justo después de iniciar la aplicación, se crea un nuevo documento. A continuación, se crean la ventana principal y sus controladores de vista, pero el método anterior devuelve nil. Aquí está el registro (usando NSLog) me sale:

Just created this new document: <MyDocument: 0x10040ff10> 
I'm in a view controller and current document is (null) 

Después de eso, la creación de un nuevo documento y llamar a este método en un puntero no nulo, pero no señala en el documento correcto, pero al primero:

Just created this new document: <MyDocument: 0x100437e10> 
I'm in a view controller and current document is <MyDocument: 0x10040ff10> 

en cuenta que después de la segunda creación de documentos, currentDocument apunta al primer documento y no a la segunda.

¿Alguna idea de lo que me estoy perdiendo o haciendo mal aquí? ¿Cuándo se establece currentDocument para NSDocumentController?

Respuesta

2

De la documentación de Apple en NSDocumentControllercurrentDocument que dice:

Este método devuelve nil si se llama cuando su aplicación no es activo. Esto puede ocurrir durante el procesamiento de una operación de arrastrar y soltar, por ejemplo, , en una implementación de readSelectionFromPasteboard :. En tal caso, envíe el siguiente mensaje en lugar de un NSView subclase asociada al documento:

[[[self window] windowController] document];

Esta cifra es ligeramente imprecisa, ya que no tiene las credenciales lo que "no activo" significa. Podría ser que una operación de arrastrar y soltar sea el único activador, pero no indica si ese es el único factor desencadenante para que una aplicación no esté activa.

Tal vez la alternativa sugerida por Apple sea útil para usted.

+0

Gracias, pero ya lo intenté y sigo sin obtener ningún resultado. Tampoco estaba seguro de qué significaba "no activo" para Apple, pero en mi caso ocurre justo después de iniciar la aplicación. Sin arrastrar y soltar, nada especial. – msoler

0

algún motivo no se puede llamar -[self document] de su NSWindowController subclase (o -[[self window] document] en su NSViewController subclase? Eso es normalmente cómo se hace esto en una aplicación basada en documentos en Cocoa.

Básicamente cuando el (subclase NSDocument) se crea, luego crea todos los NSWindowControllers y los adjunta al documento.

Más importante aún, [[NSDocumentController sharedController] currentDocument] no devolverá la información correcta si tiene 2 documentos abiertos y de repente necesita dibujar los contenidos de ambos. En su lugar, se supone que el NSWindowController controla el flujo de información a las vistas en su ventana para que pueda administrar los cambios de primer plano y fondo al mismo tiempo (como podría suceder si la tienda de respaldo para todas las ventanas en su aplicación necesitara ser refrescado al mismo tiempo).

+0

Gracias. Desde la subclase NSViewController no es posible acceder al documento llamando al documento '[[self window]]] ya que NSViewController tiene una propiedad _view_ pero no una propiedad _window_. Utilizando el documento '[[[self window] windowController] document]' desde un NSView y el documento '[[[self view view] windowController] document]' (según lo apunta @roger) desde un NSViewController, haga clic y devuelva el documento correcto. Es importante mencionar que funcionan una vez que las ventanas/vistas se han inicializado, lo que es bueno y comprensible para mí. – msoler

+0

Lo siento, me olvidé de que estaba usando NSViewControllers. He agregado otra respuesta que va más al paradigma MVC cuando se usa NSViewControllers. Espero que este sea más útil. – gaige

6

(Dejo la respuesta anterior en su lugar porque responde a la pregunta cuando me preguntaron por una subclase de NSView, pero ahora que el cartel original ha declarado que estaba usando NSViewController, hay diferentes consideraciones).

En el caso de una vista controlada NSViewController, el NSViewController está destinado a conectarse a sus datos mediante la propiedad representedObject. Esta abstracción está destinada a ser administrada por el controlador que contiene NSViewController, que suena como su NSWindowController.

Dependiendo de la cantidad de encapsulado que desee/necesite proporcionar, puede enviar el documento a NSViewControllers (si operan en el documento completo) o enviar solo la información del documento que corresponde al NSViewController particular. .

Por ejemplo, asumiré una pieza de software que edita información de diseño sobre un tren: el motor, los automóviles y el furgón de cola. La subclase NSDocument contiene un único objeto de motor, un único objeto de caboose y 0 o más objetos de automóvil. En este caso, puede tener 3 NSView s, cada uno con su propio NSViewController para manejar los datos en movimiento dentro y fuera de las vistas desde sus objetos.

El NSWindowController maneja la configuración de cada NSViewControllerrepresentedObject en el objeto que entiende. Por ejemplo, cuando los puntos de vista terminar la carga, el controlador de ventana se dividirá en:

[engineViewController setRepresentedObject: engine]; 
    [cabooseViewController setRepresentedObject: caboose]; 

A continuación, se puede utilizar un NSTableView para mostrar la lista de los coches, y (cuando un coche se está viendo), el controlador de la ventana podía luego use [carViewController setRepresentedObject: car]; cuando se cambie la selección (o podría usar enlaces, dependiendo de cómo esté estructurado su código).

De esta manera, aprovecha al máximo el paradigma MVC, ya que los controladores vinculan las vistas a los modelos según sea necesario, pero la estructura del documento solo es realmente comprendida por NSWindowController de nivel superior.