NSDocumentController currentDocument returning nil

独自空忆成欢 提交于 2019-12-06 21:06:39

问题


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 NSViews, 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!