Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

John Baughman

macrumors regular
Original poster
Oct 27, 2003
100
0
Trying to wrap my ahead around the basic concepts here. in my understanding the Controller is the glue between the Model and the View. Typically I see drawings of the Controller at the apex of a triangle with the Model and View at the 2 base points of the triangle with 2 way arrows pointing between the Controller and the Model as well as the Controller and the View.

There is no arrow between the Model and the View which implies that in a well written app there needs be no communication between the Model and the View directly. Is this true?

When the Model changes, the Controller notifies the view to update. But to update itself doesn't the View access the model for the updated data directly?

Specifically using the Stanford course assignment 3 as an example, in the view.h file I have...

IBOutlet *PolygonShape;

PolygonShape is the Model. This works great as IB wires the View to the Model and I can then update the View with the Model's data directly when notified to do so by the Controller, but doesn't this go against the MVC conceptually? Should I somehow be getting the data through the Controller?

Thanks,

John
 
MVC means different things to different people.

In the prototypical definition -- the one developed with Smalltalk -- the view is an observer of the model. When the model updates, it notifies all of its views, and the views update themselves based on the new model information. In that model, the controller is really just coordinating IO from the user, deciding what models to load, and then composing the views in a particular way.

But Apple uses MVC a little differently. Their controller is more of a marshall -- a class which acts as a go-between to update views based on model changes.
 
There will be times when a view class will explicitly "hold on" to some kind of model.

Core Animation backed views come to mind. The Core Animation Layer (CALayer) is essentially a *model* class, but the view keeps one of these models that it displays from.

I think of Core Graphics Images as model classes, but Image Views will hold on to a CGImageRef behind the scenes somewhere (right?).

Sometimes this is a more convenient way to do things, but I do think it was irresponsible to put the Polygon Shape model class in the view for a group of students who are learning Cocoa design patterns.
 
It is my understanding that you design your model classes and view classes to be as reusable as possible, and that the controller classes are the App-specific mediators which can't really be re-used. So you may design some view classes that create an iTunes-like organization for viewing and updating your data. If you design those views generically enough, you could then re-use those views to access a very different type of data in a totally un-related application. For example, you might write an app that has an iTunes style interface for organizing/managing your .pdf's on disk. In theory, you could then swap out the model classes, re-archetect the controllers and re-use the view classes and have a similar looking interface for an app that keeps track of football stats or some other thing.

In reality, most view classes will probably need some revision to make them appropriate for the context of their app, but hopefully you can see why the separation might be useful. One situation that's much more likely to be reused is custom UI controls. Matt Gemmell has stated that one should always design your custom controls as separate projects so they are easier to reuse (by controls we're actually talking about view classes that are used to interact with the app, not app-specific controller classes--sorry if that's confusing). One example he's talked about in his NSConference 2009 video (not free unfortunately) is a radial menu. If it were designed specifically for the original app, then it's usefulness is limited to just that app, whereas if it's written generically, one can wire it up to different App-controllers and use it in many other apps.

Like view classes, model classes should be designed to also be independent. For example, you could design a model class that goes out to the internet and looks up football stats and saves them to disk. If written correctly, this class could be useful in a variety of different apps, such as the previously mentioned iTunes style football stats app, but it could also be used in a completely separate command-line app, an app for the team accountant for calculating player performance bonuses, a dashboard widget, or even in an iPhone app. Another example might be a model class that performs physics calculations. This class could be useful in an architecture app used to simulate the effects of various forces on structures, but it could also be useful in a game.

I hope you found that helpful. I'm no expert, so please feel free to correct any misunderstandings I may have about MVC.
 
In the prototypical definition -- the one developed with Smalltalk -- the view is an observer of the model. When the model updates, it notifies all of its views, and the views update themselves based on the new model information. In that model, the controller is really just coordinating IO from the user, deciding what models to load, and then composing the views in a particular way.

This sounds like Cocoa with bindings in place.

But Apple uses MVC a little differently. Their controller is more of a marshall -- a class which acts as a go-between to update views based on model changes.

This sounds like early Cocoa. Without bindings, you needed some sort of marshall, and the controller usually took on that role because it already existed, and usually had references to both the model and view.

And of course, it gets interesting because you have delegates to help the view, customize its display behavior, and understand the model. Some people combine this with the controller for that particular view for whatever reason.
 
Thanks to all who participated in this thread. For the most part it confirmed to me that MVC is certainly not a hard and fast rule, but is a good basis to use in the design of an application.

... but I do think it was irresponsible to put the Polygon Shape model class in the view for a group of students who are learning Cocoa design patterns.

I put it there because I could not figure out how to access the properties of PolygonShape (the model) from the view. Which is what prompted my question re MVC in the first place... How do I access the models properties through the controller?

In Controller.h I have...

IBOutlet PolygonShape *polygon;
IBOutlet PolygonView *view;

Which gives me access to both the model and the view from the controller.

What do I put in the view so that it can access what it needs to display the model. The only way I could get it to work was to wire the view directly to PolygonShape.

And what about other objects in the window. If the view needs to know their state or values, should it also look to the controller for these values, or just wire the view directly to the desire objects.

Thanks,

John
 
What do I put in the view so that it can access what it needs to display the model. The only way I could get it to work was to wire the view directly to PolygonShape.

You have a controller that has an instance of a PolygonShape. You have a view that "needs" this shape.

What I would do is make your controller a delegate of your view. Whenever you send setNeedsDisplay: to your view, your view will call back to your controller to find out exactly what kind of PolygonShape should be displayed.

Here is one practical advantage to using this approach:

Usually, when you are working with model classes, there is something going on to change the data in that model. Suppose that our model is just a simple C structure. The user is turning some switches or typing some input; something is changing that model around. If the model is hard-coded into your view class, one way to update changes is to keep sending the view new copies of the model every time something changes. Another way is that every time your view needs a model, it calls back to the controller to see what the "current" model is. I think this is a cleaner approach.

I guess I would understand that for beginning students in the Stanford course, delegation might seem like a confusing subject (it took a while for me to get my head around what it does), but it is am important design pattern that you see over and over again in the Cocoa APIs.
 
What do I put in the view so that it can access what it needs to display the model. The only way I could get it to work was to wire the view directly to PolygonShape.

I don't even understand how it would work if you wired it directly to the model. Don't you need access to the instance, not the model. The instance is what has the number of sides you want, not the model.

Granted I haven't been able to get it to work at all so any more help would be appreciated.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.