How does NSDocumentController slot into my document based app?
I'm building my first serious Cocoa app. It is a document based app using Core Data for persistent storage. Using the Xcode "New project" template options, my project started with a couple of default classes:
- MainMenu.xib (the main menu of my app)
- EventDocument.xib (the main window of my app)
- EventDocument.h and EventDocument.m (the persistent document class)
I took the design from there and it all works rather nicely, however through another question I came across a Cocoa class NSDocumentController which I was not aware of. This class apparently offers default logic for managing document classes in a document based application.
My question is how does this class slot into my app - if at all - and do I need it? At this moment, I use the EventDocument class as a sort of top level controller. It picks up the user choices from the menu (a tree view with options a la iTunes), brings up the different views/controllers that handle these options and passes around the Managed Object Context. If NSDocumentController is "the way to go", why does Apple not generate it as part of the project template??
I believe you’re misunderstanding the goal of NSDocumentController, probably because its name is similar to NSWindowController and NSViewController.
In Cocoa MVC, a controller mediates a view and a model. When dealing with windows, it’s common for the controller to be a subclass of NSWindowController and, in the case of views, a subclass of NSViewController.
In the document-based architecture, an NSDocument class is a mediator between the model that represents the document and the corresponding views and controllers. Essentially, it is responsible for recreating the model based on an external representation and providing some way of attaching controller behaviour corresponding to the model and the view. Two designs are commonly used for that:
The NSDocument subclass effectively acts as a window (potentially view as well) controller — for example, by implementing IBActions. This should work for simple applications but it can quickly lead to a bloated NSDocument subclass that deals with more than it should. The documentation says:
The default Document-based Application project template does not subclass NSWindowController. You do not need to subclass NSWindowController if you are writing a simple application. However, if you are writing an application with more advanced requirements, you will almost certainly want to do so.
The NSDocument subclass creates custom window controllers, which in turn implement controller behaviour, potentially using view controllers as well.
In many (most?) cases there is no need for an NSDocumentController subclass — the controller part of your application would be inside window controllers, view controllers, or your NSDocument subclass. That said, there are some situations where it might be necessary as explained in the documentation:
Usually, you should not need to subclass NSDocumentController. Almost anything that can be done by subclassing can be done just as easily by the application’s delegate. However, it is possible to subclass NSDocumentController if you need to.
For example, if you need to customize the Open panel, an NSDocumentController subclass is clearly needed. You can override the NSDocumentController method runModalOpenPanel:forTypes: to customize the panel or add an accessory view. The addDocument: and removeDocument: methods are provided for subclassers that want to know when documents are opened or closed.