问题
I'm working on my first Mac document-based application.
I have subclassed NSDocument
, reimplementing methods such as
- (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError;
- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError;
- (void)makeWindowControllers;
The main window controller is a subclass of NSWindowsController
, that contains two NSViewController subclasses.
The problem I'm facing is that I need to have access to the current document from these view controllers. What I do is calling
MyDocument *myDocument = [[NSDocumentController sharedController] currentDocument];
At first, right after starting the application, a new document is created. Then, the main window and its view controllers are created, but the method above returns nil. Here's the log (using NSLog) I get:
Just created this new document: <MyDocument: 0x10040ff10>
I'm in a view controller and current document is (null)
After that, creating a new document and calling this method results in a non-nil pointer, but it doesn't point at the right document, but to the first one:
Just created this new document: <MyDocument: 0x100437e10>
I'm in a view controller and current document is <MyDocument: 0x10040ff10>
Notice that after the second document creation, currentDocument
points to the first document and not to the second one.
Any idea of what I'm missing or doing wrong here? When is currentDocument
set for NSDocumentController
?
回答1:
(I'm leaving the previous answer in place because it answers the question when asked for a subclass of NSView, but now that the original poster has stated he was using NSViewController, there are different considerations).
In the case of an NSViewController
-controlled view, the NSViewController
is intended to be attached to its data using the representedObject
property. This abstraction is intended to be managed by the NSViewController's containing controller, which sounds like is your NSWindowController
.
Depending on how much encapsulation you want to/need to provide, you can either push the document to the NSViewControllers (if they operate on the whole document) or push just the information from the document that is germane to the particular NSViewController.
For example, I'll assume a piece of software that edits design information about a train: the engine, the cars, and the caboose. The NSDocument
subclass contains a single engine object, a single caboose object, and 0 or more car objects. In this case, you might have 3 NSView
s, each with their own NSViewController
to handle moving data in and out of the views from their objects.
The NSWindowController handles setting each NSViewController
's representedObject
to the object it understands. For example, when the views finish loading, the window controller will then:
[engineViewController setRepresentedObject: engine];
[cabooseViewController setRepresentedObject: caboose];
Then, you can use an NSTableView to show the list of cars, and (when a car is being viewed), the window controller could then use [carViewController setRepresentedObject: car];
when the selection is changed (or you could use bindings, depending on how your code is structured).
This way, you take the best advantage of the MVC paradigm, as the controllers link the views to the models as necessary, but the document structure is only really understood by the top level NSWindowController.
回答2:
From the Apple documentation on NSDocumentController
currentDocument
it says:
This method returns nil if it is called when its application is not active. This can occur during processing of a drag-and-drop operation, for example, in an implementation of readSelectionFromPasteboard:. In such a case, send the following message instead from an NSView subclass associated with the document:
[[[self window] windowController] document];
This is slightly vague as it doesn't really qualify what "not active" means. It could be that a drag 'n drop operation is the only trigger but it doesn't state whether that's the only trigger for an app to become not active.
Maybe the suggested alternative by Apple is of use to you.
回答3:
Any reason you can't call -[self document]
from your NSWindowController
subclass (or -[[self window] document]
in your NSViewController
subclass? That's normally how this is done in a document-based app in Cocoa.
Basically when the NSDocument
(subclass) is created, it then creates all of the NSWindowControllers and attaches them to the document.
More importantly, [[NSDocumentController sharedController] currentDocument]
won't return the right information if you have 2 documents open and suddenly need to draw the contents of both. Instead, the NSWindowController
is supposed to control the flow of information to the the views in its window so that you can manage foreground and background changes at the same time (such as might happen if the backing store for all windows in your app needed to be refreshed at the same time).
来源:https://stackoverflow.com/questions/8912314/nsdocumentcontroller-currentdocument-returning-nil