2012-01-18 16 views
9

Sto lavorando alla mia prima applicazione basata su documenti Mac.NSDocumentController currentDocument restituito nil

ho sottoclasse NSDocument, reimplementando metodi come

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

Il controllore finestra principale è una sottoclasse di NSWindowsController, che contiene due NSViewController sottoclassi.

Il problema che sto affrontando è che ho bisogno di avere accesso al documento corrente da questi controller di vista. Quello che faccio è chiamare

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

In un primo momento, subito dopo l'avvio dell'applicazione, viene creato un nuovo documento. Quindi, vengono creati la finestra principale e i relativi controller di visualizzazione, ma il metodo sopra restituisce nil. Ecco il registro (utilizzando NSLog) ottengo:

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

Dopo di che, la creazione di un nuovo documento e chiamare questo metodo comporta un puntatore non nullo, ma non punta verso il documento giusto, ma al primo:

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

noti che dopo la seconda la creazione di documenti, currentDocument punti al primo documento e non alla seconda.

Qualche idea di ciò che mi manca o che non funziona qui? Quando è impostato currentDocument per NSDocumentController?

risposta

2

Dalla documentazione Apple su NSDocumentControllercurrentDocument dice:

Questo metodo restituisce nil se viene chiamato quando la sua applicazione non è attiva. Ciò può verificarsi durante l'elaborazione di un'operazione di trascinamento della selezione, ad esempio , in un'implementazione di readSelectionFromPasteboard :. In un tale caso, inviare il seguente messaggio invece da un NSView sottoclasse associata al documento:

[[[self window] windowController] document];

Questo è un po 'vaga, come in realtà non qualifica che cosa "non attivo" significa. Potrebbe essere che l'operazione di trascinamento e rilascio sia l'unico trigger, ma non indica se è l'unico trigger che un'app diventa non attiva.

Forse l'alternativa suggerita da Apple è utile.

+0

Grazie, ma l'ho già provato e sto ancora ottenendo zero come risultato. Ero anche incerto su cosa significasse "non attivo" per Apple, ma nel mio caso accade subito dopo aver avviato l'app. Nessun drag-and-drop, niente di speciale. – msoler

0

Qual è il motivo non è possibile chiamare -[self document] dal NSWindowController sottoclasse (o -[[self window] document] nella tua NSViewController sottoclasse? Ecco normalmente come questo viene fatto in un'applicazione basata su documenti in Cocoa.

Fondamentalmente, quando il NSDocument (sottoclasse) viene creato, quindi crea tutti i NSWindowController e li allega al documento.

Ancora più importante, [[NSDocumentController sharedController] currentDocument] non restituirà le informazioni corrette se sono aperti 2 documenti e improvvisamente è necessario disegnare il contenuto di entrambi. Invece, lo NSWindowController deve controllare il flusso di informazioni per le viste nella sua finestra in modo da poter gestire contemporaneamente le modifiche in foreground e in background (come potrebbe accadere se fosse necessario il backing store per tutte le finestre della tua app) aggiornato allo stesso tempo).

+0

Grazie. Dalla sottoclasse NSViewController non è possibile accedere al documento chiamando '[[self window] document]' come NSViewController ha una proprietà _view_ ma non una proprietà _window_. Usando il '[[[self window] windowController] document' 'da un NSView e' [[[[self view] window] windowController] documento '(come indicato da @roger) da un NSViewController funzionano e restituiscono il documento giusto. È importante menzionare che funzionano una volta che le finestre/viste sono state inizializzate, il che è soddisfacente e comprensibile per me. – msoler

+0

Mi dispiace, ho perso il fatto che stavi usando NSViewControllers. Ho aggiunto un'altra risposta che va più al paradigma MVC quando si utilizza NSViewControllers. Spero che questo sia più utile. – gaige

6

(Lascio la risposta precedente in posizione perché risponde alla domanda quando viene richiesta una sottoclasse di NSView, ma ora che il poster originale ha dichiarato che stava usando NSViewController, ci sono diverse considerazioni).

Nel caso di una vista controllata NSViewController, il NSViewController deve essere collegato ai propri dati utilizzando la proprietà representedObject. Questa astrazione deve essere gestita dal controller contenente NSViewController, che suona come il tuo NSWindowController.

A seconda della quantità di incapsulamento che si desidera/deve fornire, è possibile inviare il documento agli NSViewControllers (se operano sull'intero documento) o solo le informazioni dal documento che è pertinente al particolare NSViewController .

Ad esempio, assumerò un software che modifica le informazioni di progettazione relative a un treno: il motore, le macchine e il vagone. La sottoclasse NSDocument contiene un oggetto motore singolo, un singolo oggetto caboose e 0 o più oggetti auto. In questo caso, potresti avere 3 NSView s, ciascuno con il proprio NSViewController per gestire i dati in movimento dentro e fuori le viste dai loro oggetti.

Il NSWindowController gestisce l'impostazione di ogni NSViewControllerrepresentedObject sull'oggetto che comprende. Ad esempio, quando il punto di vista finire di carico, il controller della finestra sarà quindi:

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

Quindi, è possibile utilizzare un NSTableView per visualizzare l'elenco delle auto, e (quando una macchina sta osservando), il controller finestra poteva quindi utilizzare [carViewController setRepresentedObject: car]; quando la selezione viene modificata (oppure è possibile utilizzare le associazioni, a seconda di come è strutturato il codice).

In tal modo, si sfrutta al meglio il paradigma MVC, poiché i controllori collegano le viste ai modelli secondo necessità, ma la struttura del documento viene compresa solo dal NSWindowController di livello superiore.