If you’re trying to write your first iPhone/iTouch applications or are struggling to put together a small to medium size application, this article may help.
This article assumes you have the ‘kind of understand’ feeling about MVC that most programmers get after digging up a little material on the topic.
A Basic Model View Controller (MVC) setup
In xcode, select new project > view based application. The following classes are created for a ‘Z’ project:
ZAppDelegate – Application Facade
ZViewController – Root controller
The only classes missing are a view class and a model class.
Basic view setup:
- Create a ZView class if you need to customise the view provided by ZViewController.xib programmatically. Assign ZView as class of the root controller’s view from the property inspector in interface builder.
- If you only want to gain access to UI elements added to the view, do the following:
1 – open ZViewController.xib and add your UI elements. In this example, I assume a label (UILabel class) was added.
2 – add an IBOutlet field to ZViewController.h, like this :
IBOutlet UILabel* myLabel;
3 – In ZViewController.xib, notice that myLabel now appears in the file’s owner property inspector (click the blue arrow pointing right in prop inspector to view outlets). It has a little keyhole on the right.
4 – From myLabel‘s keyhole, click-drag a connector to the actual label.
Step 1 creates the actual UI element. Step 2 allows programmatic access to the created UI element. Finally, Steps 3 and 4 ensure that the field we have created maps to the actual UI element.
1 – Where do we create the model? In other words, when should it be initialized?
2 – How do we provide the controller and view a reference to the model
These questions can be answered in various ways. For simple applications, here’s a recipe that works.
- Instantiate your model class in ZAppDelegate::applicationDidFinishLaunching
- Still in the same function, assign the model to the controller and view.
ZAppDelegate naturally owns a reference to the controller (viewController) and view (viewController.view). This makes it a convenient placeholder for our data model. Besides, even if we change the controller and/or view while the application is running, we can still access the model root. Finally, applicationDidFinishLaunching clearly holds the code used to add the view to the main window, so we are sure that the view binds the model before getting rendered the first time.
Processing user interaction
If your view is processing touches (touchesBegan etc…) it may be convenient to assign a backward reference from the view to the controller. Again, this setup can be effected from applicationDidFinishLaunching. We can then query the controller to perform high level actions when touches occur.
You can work around potential (compile-time) cyclical dependencies between the view and controller by only referring the controller using an
annotation before your interface declaration/class def. Although this may trigger a warning, you don’t need to import ZViewController to invoke methods on it as Objective C resolves method calls at runtime.
That’s it for now…
If your application is becoming complex, you may need to look into more developed MVC solutions – e.g. get inspiration from the PureMVC framework or maybe try my F* Meta-Pattern.