I want my application to have a single document but several screens without resorting to several windows. What's the best way to achieve this? I'm thinking of using a single NSPersistentDocument that will start with a NSViewController displaying a set of controls and then swap that view for another NSViewController.
My question is: is this the correct use of NSViewControllers? Can it even be done? And if the answer to both is yes, how do I swap a view for another in a document?
Yes, it's completely possible to do. Yes, you should use view controllers but you don't have to. That's strictly a stylistic choice. If you don't use a view controller then all the controller logic would likely be in your single window controller. That might get painful for a big app. View controllers help you break down your UI into logical components and control units.
You'd go about doing the view controller method like this:
- Create separate xibs for each of your component views.
- For each xib, create a view controller subclass that loads, owns, and controls it.
- You could go further with this and have sub view controllers for separate areas within views.
- In your awakeFromNib class of your window controller, instantiate all your top-level view controllers.
Now you've got the basic framework for an app with multiple top-level view controllers. From here the task is to arrange the views in the main window as you need them or as user input dictates. Sometimes you might have 3-4 top-level views sometimes 1, and in your case you just want to swap out one for the another. There is no huge difference between these scenarios.
There are many ways to achieve this.
For your specific case, an easy way to go about it is:
- Use a top-level tabless and borderless tab view and set the selected tab programmatically.
In general you can do a bunch of things:
- Manually arrange the sub views in the main window's content view.
- Move (animate) sub views in/out or within the viewable area as needed.
- Use split views in the main window to collapse and uncollapse areas that you want or don't want showing.
BTW this method works regardless of whether you are creating a document-based app or not or whether it is a single-window or multi-window document based app.
The one downside to using view controllers is a lot of the top-level view layout and management has to be done programmatically and not in IB. But it's not that difficult.
Usually you just need to do a addSubview: and setFrame:, to place your views in a parent view you already laid out in IB.
But to do more complicated and manual stuff you should read up on the docs and get to know how the following work: frame/bounds, flipped coordinates, autoresizing, and how to override autoresizing to do your own layouts.
- Introduction to View Programming Guide for Cocoa
It can be done as you describe but you will have to manage the relationship to the document manually because the default configuration assumes a one-document --> one-controller relationship for simplicity sake.
Once move away from the standard design, you lose all the built-in functionality.
You might want to rethink your design. The purpose of linking a document to a specific view controller is to provide the user with a metaphor for the document. The view is the document as far as the user is concerned. If you provide multiple views of the same document, the user is most likely to interpret that has multiple documents because that is what the UI grammar has trained them to expect.
When you find yourselves doing something nonstandard in the UI, stop and think carefully. Just because you as the developer understands what is going on doesn't mean the user will.
What about using a NSNavigationController to manage the multiple views - it makes it easy to push and pop the various views ?