MVC woes in Xcode/Interface Builder

Apprentice
Posts: 7
Joined: 2008.11
Post: #1
I've just started a Cocoa application project. I have a single window with a single NSOpenGLView subclass, where the OpenGL view is able to receive mouse and keyboard events. I intend my OpenGL to have a pointer to a Game object, which gets fed input events and draws the scene in the view's drawRect method.

Now, since the creation of all of the interface elements are hidden away in my NIB file, is creating a Game inside my OpenGL view (in the initWithFrame I assume) the only way of giving the OpenGL view a Game? It's just that I'm not sure my view should really be concerned with the creation of the Game (the model in MVC terms). This is especially the case since my Game will actually be implementing the state pattern, where it may be delegating its tasks to a TitleState or a PlayState. This would make creation of the Game object may be complex and deal with more things than the view should.

I also can't tell how to do other things outside of my view. For example, I'll want to load resources like sound and graphics into memory, a process that the view should have nothing to do with. But in Xcode and Interface Builder I see no entry point besides in my view code where I'd override initWithFrame or something.

Essentially, I'm having trouble seeing how I'm able to separate my view from my model in Cocoa, which is kind of strange when Cocoa is supposed to implement the MVC pattern.

P.S. I've read that in order to capture mouse movement events, I have to call setAcceptsMouseMovedEvents on my window. I don't see any equivalent setting in Interface Builder, so where do I put such a call?
Quote this message in a reply
Moderator
Posts: 3,570
Joined: 2003.06
Post: #2
I don't personally bother with specifically trying to carry MVC over into the game. If you're really intent on doing so, I find it easier to look at the game as a new layer of MVC within the view. Games are very specialized applications and can be quite complex, so don't be afraid to break "the rules" when you want to.

Also, many of us set up our glView programmatically instead of using InterfaceBuilder for much of anything, except OS windows/menus/etc.
Quote this message in a reply
⌘-R in Chief
Posts: 1,237
Joined: 2002.05
Post: #3
Quote:...is creating a Game inside my OpenGL view (in the initWithFrame I assume) the only way of giving the OpenGL view a Game?

Of course not. You can create it anywhere in code and simply pass it to your NSOpenGLView subclass. There's a C in MVC; Your controllers are responsible for linking model and view information.


Quote:I also can't tell how to do other things outside of my view.

I'm not sure why you're hung up on the view. There's no reason you can't create any number of other classes, and have them do the work for you. When your nib loads -awakeFromNib is called on any objects there. You could add an instance of your controller class to the top-level of the nib and use -awakeFromNib to do any initial setup and loading, etc.


Quote:Essentially, I'm having trouble seeing how I'm able to separate my view from my model in Cocoa, which is kind of strange when Cocoa is supposed to implement the MVC pattern.

It's absolutely no different than anywhere else. You simply need to create your controller classes and use them.



Quote:P.S. I've read that in order to capture mouse movement events, I have to call setAcceptsMouseMovedEvents on my window. I don't see any equivalent setting in Interface Builder, so where do I put such a call?

.... In your code. [window setAcceptsMouseMovedEvents:YES];

You need to call that from some class that actually has a reference to the window. (Such as an IBOutlet, if the window is created in a nib.)
Quote this message in a reply
Apprentice
Posts: 7
Joined: 2008.11
Post: #4
FreakSoftware Wrote:Of course not. You can create it anywhere in code and simply pass it to your NSOpenGLView subclass. There's a C in MVC; Your controllers are responsible for linking model and view information.

...

I'm not sure why you're hung up on the view. There's no reason you can't create any number of other classes, and have them do the work for you. When your nib loads -awakeFromNib is called on any objects there. You could add an instance of your controller class to the top-level of the nib and use -awakeFromNib to do any initial setup and loading, etc.

So, I take it the usual practice is to initialize my Game, load any resources, etc., in one of my controller objects, right? Or is it also possible to put other objects inside my nib files besides Views and Controllers, like my Game object?

It's just that I'm used to the C/C++ (and maybe Java) way of doing thing. I'd start with a single main function or static method where I create all of my models, views, and controllers and link them together. Of course the view is not responsible for creating the model, and I never thought the controller was responsible either (am I wrong in this part?). I always saw the controller as just mediating events between the views and models, while the process of creating and linking these things together was done by something else at the start of program execution. This is why I get confused when I delve into Cocoa, where there doesn't seem to be any place to put this initialization code code into some place that wouldn't "pollute" the views and controllers (if such a thing would pollute the controller).

For example, in [url=http://developer.apple.com/documentation/cocoa/conceptual/objctutorial/06Controller/chapter_6_section_7.html#//apple_ref/doc/uid/TP40000863-CH8-SW21]Apple's Cocoa tutorial[/i], the controller needs a model for currency conversion, so it creates a new model object every time it needs one. I wish the example dealt with something requiring some kind of persistent model, since that's the sort of thing I'm confused about.
Quote this message in a reply
⌘-R in Chief
Posts: 1,237
Joined: 2002.05
Post: #5
You can instantiate any object you want inside a nib. A nib isn't really special at all. A nib is more or less just an list of class instances to create, and a bunch of settings to apply to those instances. The settings are stored in serialized form via the NSKeyedArchiver/Unarchiver classes. Settings would be things like, the view positions, enabled, button type, etc. The nib also keeps lists of references to other objects -- IBOutlets and then sets them.

If it helps, you can think of a nib file as doing nothing more than this:

Code:
for each item in nib
     instance = [[class alloc] initWithCoder:coderWithSettings];
end

for each created instance
     for each specified outlet
          instance->outlet = otherInstance;
     end
end

for each created instance
     [instance awakeFromNib];
end


And this happens when you simply load the nib:

[code]
success = [NSBundle loadNibNamed:@"MyNib" owner:controllerObj];
[/quote]

"controllerObj" would be File's Owner in the nib.

MainMenu.nib is loaded by NSApplication which is why File's Owner in MainMenu.nib is NSApplication.


-----------------

Quote:Of course the view is not responsible for creating the model, and I never thought the controller was responsible either (am I wrong in this part?).

Yes. Something has to be responsible. If not the view, then what else is there? (TypicallySmile Controllers create models, views display models, and controllers mediate as necessary as you said.


Quote:I always saw the controller as just mediating events between the views and models, while the process of creating and linking these things together was done by something else at the start of program execution.

What happens when you create a new document by choosing File -> New in, for example, a text editor? It creates a new model (the text document storage), a view (the text field that you type into), and a new controller (NSWindowController typically) to manage them as necessary.

All of these objects obviously don't get created in main(). They get created by... a controller. NSDocumentController to be precise. NSDocumentController gets sent the newDocument: action from the menu item and creates a new NSDocument instance, NSDocument actually creates its required controllers (NSWindowControllers), and the window controllers (typically) load nib files containing all of their views, possibly other subcontrollers (ie view controllers), and whatever else there is.

Where does NSDocumentController come from? NSApplication creates it. Who creates NSApplication? NSApplicationMain() inside of main(). So everything is created by either a model a view or a controller, except (typically) one root object, which in Cocoa is NSApplication.


Quote:It's just that I'm used to the C/C++ (and maybe Java) way of doing thing. I'd start with a single main function or static method where I create all of my models, views, and controllers and link them together

It really isn't a difference between languages. Your C++ code could do exactly the same thing. One root object from which a whole tree is created. Not everything is created in main(), and in an event-driven application, most objects aren't created until the user triggers and event to create them.


Quote:This is why I get confused when I delve into Cocoa, where there doesn't seem to be any place to put this initialization code code into some place that wouldn't "pollute" the views and controllers (if such a thing would pollute the controller).

There "aren't places to put your code" because you need to *make* the objects in which to put that code. In a plain bare-bones Cocoa application where all it does is simply create an NSApplication instance for you (which loads MainMenu.nib), you typically would create some other controller class and instantiate it in the nib, probably make it NSApplication's delegate, and probably from within the applicationDidFinishLaunching: delegate method, do whatever you want.

From there it's nothing about what Cocoa "lets" you do, you just have to do it yourself.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  ibtool failed ...: Interface Builder error communicating with simulator sefiroths 1 3,494 Nov 4, 2011 06:52 AM
Last Post: sefiroths
  Picture in Interface Builder skyhawk 1 3,006 Jun 15, 2006 02:10 PM
Last Post: OneSadCookie