8
votes

So I'm beginning to learn how to use Cocoa. I think I've pretty much got it but I'm hung up on creating and switching views. I'm rewriting a game I made a little bit ago for practice. All I want is one window (preferably not resizable) and I want to be able to switch out views for different screens in the game.

First, I have the main menu (Start Game, High Scores, Exit). Then I need a window for each screen (Gameplay screen, Highscore screen).

What I'm getting confused with is how to design this. I looked up NSViewController thinking it manages views but it doesn't. It only manages one view by loading it really. I don't understand why I'd need to use NSViewController then. Couldn't I just have a window class that contains multiple subclasses of NSView and load them like that? I'm not sure I understand the purpose of the ViewController.

Does my Window Class really need to subclass NSWindowController? I was trying to follow the example of Apple's ViewController example and it has a window controller class that's a subclass of NSWindowController. I don't see what the purpose was of subclassing that. All NSWindowController seems to add is - initWithPath:(NSString *)newPath but I fail to see the use in that either when I can just edit the plist file to open the window on start up. Apple's example also has an NSView variable and an NSViewController variable. Don't you only need one variable to store the current view?

Thanks in advance guys, I'm really confused as to how this works.

4

4 Answers

6
votes

It sounds like you're trying to swap out the content view within a window? If that is the case, you can use -[NSView replaceSubview:with:] with -[NSWindow contentView] as the receiver.

Say you have a title page named titleView and a menu page named menuView and you want to swap these in and out of your application's main window. If the title page is visible and the user clicks on a "main menu" button or link, you would put something like this in the button's delegate method:

[[[NSApp mainWindow] contentView] replaceSubview:titleView with:menuView];

Two things to be aware of:

  1. The old view, titleView in this case, is released by this call. If you want it still be available, you will have to retain it prior to replacing it.
  2. The parent view will not resize if your pages have different dimensions. Changing the frame size of the window, and therefore the contentView is easy enough, but you can add a little Core Animation into the mix to give it some style.

I hope this helps!

5
votes

You use NSWindowController and NSViewController to manage a window or a view because you should only need to create subclasses of NSWindow or NSView for new "kinds" of window or view. For example, if you wanted to use a circular window, you would subclass NSWindow. If you just want to have controls in a window, you subclass NSWindowController.

It's the same with NSViewController: Generally an NSViewController's view will be of some base class such as NSView (or perhaps your own NSView subclass that draws a custom background). The NSViewController manages the interaction among the subviews of that view, allowing it to act as a single unit within your larger application.

Think of it this way: Views draw, and they turn raw input events into higher-level actions. Controllers supply information to views, and handle actions.

Composing things this way can greatly improve the modularity of your code, making it easier to design, write, and debug.

1
votes

Use following functions defined in UIVew (which is part of your existing window)

- (void)addSubview:(UIView *)view
- (void)removeFromSuperview
0
votes

I'm new to cocoa but I think your app does not really require an NSViewController. An NSViewController plays the role of "Controller" in the MVC design pattern. So it 'controls' all of the actions - the glue logic - within a single view.

For example, in a view with multiple controls: buttons, tables, checkboxes:, textfields date pickers, etc, there is likely detailed interactions between those controls that require bindings and updates. For example, a button click loads a database fetch, with error handling and validation. That glue logic goes into the NSViewController class.

In your app, it sounds like each view is a simple page with little need for view level control. So, you probably need a single NSWindowController, a controller to handle the logic and events for transitioning from page to page.

One technique for handling multiple views that fill a single window is to use a NSTabView and set the tab style to 'borderless' in IB. Then use button action to select the required NSTabViewItem. During development, set the tabview style to 'top tabs' and IB allows you to tab thru the subviews you want to display.