2014-12-30 2 views
18

Attualmente sto combattendo con NSDocument in un'applicazione Cocoa basata su storyboard basata su documenti (Objective C). Qualcuno può dirmi come posso accedere al documento nella sottoclasse NSViewController?Mac App Storyboard - Accesso al documento in NSViewController

Ho cercato di accedere nel modo seguente - ma il documento è nullo:

[self.view.window.windowController document]; 

Grazie per il vostro aiuto!

migliori saluti Martin

+0

come implementare '-makeWindowControllers' di NSDocument? chiama '-addWindowController:' come un modello predefinito? – bluedome

+0

sì è implementato come follwos: - (void) makeWindowControllers { // Override per restituire il nome del file Storyboard del documento. [self addWindowController: [[NSStoryboard storyboardWithName: @ "Main" bundle: nil] instantiateControllerWithIdentifier: @ "Document Window Controller"]]; } – Martin

+0

dove inserisci il codice '[self.view.window.windowController document]' nella sottoclasse di NSViewController? – bluedome

risposta

16

Stavo lottando con questo me stesso. Ho iniziato con il modello standard di Yosemite e stavo cercando di utilizzare [self.view.window.windowController document] in -viewDidLoad. A quel punto, self.view.window è nil, quindi non c'è modo di arrivare allo document.

Il trucco è attendere -viewWillAppear. Al momento della chiamata, self.view.window viene popolato e il numero document è disponibile.

Sequenza: -makeWindowControllers invoca -self addWindowController: con il risultato dello storyboard - instantiateControllerWithIdentifier:. -addWindowController: attiva una chiamata al VC -viewDidLoad prima di tornare. Quindi, infine, viene chiamato -viewWillAppear (e lo document è disponibile).

+1

Funziona e sto impostando il 'representationObject' del controller di visualizzazione nel metodo' viewWillAppear' sul documento del controller di finestra. Ma mi chiedo se questo sia davvero il modo in cui dovrebbe essere. Funziona, ma si sente hacky. – Pascal

+1

Aggiunta di una nota per il prossimo: se nella finestra del documento è presente un NSTableView, chiamerà i suoi metodi delegati sul viewController prima che il documento sia impostato, il che rende difficile fare cose come restituire il numero di righe. Una soluzione è mettere un 'viewWillAppear' con' myTableView.reloadData' per indurlo a chiamare i metodi dopo che il documento è valido. –

1

So che la domanda originale era per Objective-C, ma per altri che usano Swift, i protocolli possono aiutare. Il concetto di base può essere applicato anche in Objective-C.

Invece di raggiungere di nuovo al controller della finestra, è possibile utilizzare l'iniezione di dipendenza:

1) Creare una proprietà document sul controller finestra e qualsiasi controller di vista che hanno bisogno di accedere al documento (o utilizzare la proprietà representedObject che esiste già). Per semplificare l'operazione, è possibile utilizzare un protocollo per definire la proprietà del documento o per assegnare la proprietà representedObject al tipo di documento se si utilizza tale percorso. Fai in modo che tutti i controller di vista che devono accedere al documento adottino questo protocollo.

protocol DocumentAccessing { 
    var document: MyDocument? { get set } // could also use an implicitly unwrapped optional if the document is required to be set for the app to function 
} 

2) Nel metodo del documento sottoclasse makeWindowControllers(), dopo aver creato il controller finestra, impostare la sua proprietà del documento a sé (in quanto questo è il documento).

- (void)makeWindowControllers { 
    MyWindowController *windowController = MyWindowController() 
    windowController.document = self; 
    [self addWindowController:windowController]; 
} 

3) Dentro il controller finestra sottoclasse, dopo si istanzia i controller di vista, impostare la proprietà del documento del controller vista proprietà del documento del controller finestra.

4) Ora quando viene caricato il controller di visualizzazione, è necessario inserire le proprietà del documento.

1

Questo non indirizza direttamente la domanda. Ma il Q & Un link qui sotto mostra come accedere al modello dati nel tuo documento dagli oggetti NSControl usando i bind, utilizzando l'oggetto preparato di NSViewController.

https://developer.apple.com/library/content/qa/qa1871/_index.html

ho impostato il representedObject per la NSViewController nel documento.m come segue:

- (void)makeWindowControllers { 
NSWindowController* wc = [[NSStoryboard storyboardWithName:@"Main" bundle:nil] instantiateControllerWithIdentifier:@"Document Window Controller"]; 
NSViewController* vc = wc.contentViewController; 
vc.representedObject = self.model; 

[self addWindowController:wc]; 

}

Ora representedObject della mia ViewController è impostato a modello. Supponendo che il mio modello abbia una proprietà text, posso associare qualsiasi NSControl a tale proprietà tramite ViewController con keyPath: self.representedObject.text