1

I'm new to the NSDocument architecture and am looking to set up multiple windows (and hence multiple NSWindowController objects) for a single document.

From what I understand, NSDocument was really created to work with a single window, and it seems that the ability to have multiple windows was shoehorned in later. For example, it seems that the NSDocument should always be the file's owner for any window's NIB files. But what if I wanted to separate the window controllers from the document?

For example, in the NSDocument subclass I am currently using the code:

- (void)makeWindowControllers {
    [self setMyWindowController1:[[WindowControllerType1 alloc] initWithWindowNibName:@"MyWindow" owner:self]];
    [self addWindowController:[self MyWindowController1]];
}

But the NIB file "MyWindow"'s file owner is set to the NSWindowController subclass (WindowControllerType1), NOT my NSDocument subclass. In this case, whenever I look to get the document by using [[NSDocumentController sharedDocumentController] currentDocument], this ALWAYS returns nil.

I figure this can be rectified if I set the NIB file's owner to the NSDocument subclass, but then all of my outlet links break, and I'm not sure how to link to the NSWindowController subclass (WindowControllerType1), as the typical course of action (as far as I can tell) is to make the NSDocument a window controller delegate as well, which I would like to avoid!

Any suggestions?

EDIT:

Let me clarify and add some new information. I am aware of Apple's position on using the WindowController's document property. However, as I plan of having a larger number of nested NSViews in each window, I want to avoid passing the document through a large chain of views in order to accomplish this.

The issue is not necessarily this chain. It is mostly that when the [[NSDocumentController sharedDocumentController] currentDocument] is ALWAYS nil, none of the "for free" features of NSDocument seem to work, such as undo/redo. This is the major issue that I need to resolve.

Stuart Barth
  • 301
  • 2
  • 10
  • No need to pass document through the views hierarchy. You can access view.window.windowController.document (and eventually set viewController.represented object to a sub-model of the whole document model). About the currentDocument issue, I have posted an alternative solution here : https://stackoverflow.com/questions/8912314/nsdocumentcontroller-currentdocument-returning-nil – Moose Feb 08 '21 at 09:20

2 Answers2

1

From what I understand, NSDocument was really created to work with a single window, and it seems that the ability to have multiple windows was shoehorned in later.

No, makeWindowControllers is available in OS X v10.0 and later.

But what if I wanted to separate the window controllers from the document?

The window controller owns the NIB.

Any suggestions?

Do [self setMyWindowController1:[[WindowControllerType1 alloc] initWithWindowNibName:@"MyWindow"]].

NSWindowController has a property document which is set by addWindowController:.

Willeke
  • 14,578
  • 4
  • 19
  • 47
  • Thanks Willeke. I know that the functionality for multiple windows has existed from the start, but the fact that there are two methods for invoking viewcontrollers (`- (void)makeWindowControllers` and `- (NSString *)windowNibName`) seems to suggest (to me) a lack of cohesion. I'm not sure what you mean by saying that the window controller owns the nib. From Apple's documentation: "When an NSWindowController object receives a request from its owning NSDocument object, it loads the nib file containing a window, displays the window, and sets itself as the File’s Owner of the nib file". – Stuart Barth Oct 19 '15 at 01:52
  • 1
    The window controller is the NIB owner. In IB, File's owner is a (subclass of) NSWindowController. – Willeke Oct 19 '15 at 15:48
  • 1
    `-(NSString *)windowNibName)` is kind of a convenience method for one simple window. – Willeke Oct 19 '15 at 15:57
0

Use document property of NSWindowController instead of currentDocument.

reviver
  • 168
  • 1
  • 8
  • Thanks, I know of that solution, but it isn't the for me I don't think, as I'd like to avoid having to create a large variable chain through the large number of view layers I am planning on using. – Stuart Barth Oct 19 '15 at 01:42
  • 1
    I don't understand what you said, can you explain you question? – reviver Oct 19 '15 at 09:11
  • Can you have multiple documents? – Willeke Oct 19 '15 at 15:21
  • Apple's discussion of currentDocument: The value of this property is nil if it is called when the app 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];` – Willeke Oct 19 '15 at 15:32
  • @Willeke I really only want one document open at a time. – Stuart Barth Oct 20 '15 at 00:02
  • If you only need one document at a time (shoebox/library style), avoid using document architecture referring to Apple's document. Document architecture is designed to support multiple documents. – reviver Oct 20 '15 at 00:08
  • I disagree. NSDocument is designed to manage a document and window controllers. No reason to avoid it. – Willeke Oct 20 '15 at 00:42
  • @Willeke Yes, NSDocument instance represents a document and window controllers, but document architecture is designed to support multiple documents. Check the document based app guide. – reviver Oct 20 '15 at 01:08
  • I did, it doesn't say 'avoid Document Architecture'. – Willeke Oct 21 '15 at 16:07