How Xcode and Interface Builder Implement MVC
Over the past few hours, you've learned about Xcode and Interface Builder and have gotten a sense for what the two applications do. In Hour 5, "Exploring Interface Builder," you even connected objects in an XIB file to the code in an application. Although we didn't go into the nitty-gritty details at the time, what you were doing was binding a view to a controller.
Views, although possible to create programmatically, will most frequently be designed visually in Interface Builder. Views can consist of many different interface elements—the most common of which we covered in Hour 4, "Inside Objective-C and Cocoa Touch: Where the Rubber Meets the Road." When loaded at runtime, views create any number of objects that can implement a basic level of interactivity on their own (such as a text field opening a keyboard when touched). Even so, a view is entirely independent of any application logic. This clear separation is one of the core principles of the MVC design approach.
For the objects in a view to interact with application logic, they require a connection point to be defined. These connections come in two varieties: outlets and actions. An outlet defines a path between the code and the view that can be used to read and write values. Second, an action defines a method in your application that can be triggered via an event within a view, such as a touch or swipe.
So, how do outlets and actions connect to code? In the preceding hour, you learned to control-drag in Interface Builder to create a connection, but Interface Builder "knew" what connections were valid. It certainly can't "guess" where in your code you want to create a connection; instead, you must define the outlets and actions in the code that implement the view's logic (that is, the controller).
A controller, known in Xcode as a view controller, handles the interactions with a view, and establishes the connection points for outlets and actions. To accomplish this, two special directives, IBAction and IBOutlet, will be added to your project's code. Specifically, you add these directives to the header files of your view controller. IBAction and IBOutlet are markers that Interface Builder recognizes; they serve no other purpose within Objective-C.
An IBOutlet is used to enable your code to talk to objects within views. For example, consider a text label (UILabel) that you've added to a view. If you want to access the label under the name myLabel within your view controller, you would declare it like this in the header file:
Once declared, Interface Builder enables you to visually connect the view's label object to the myLabel variable. Your code can then fully interact with the label object—changing its properties, calling its methods, and so on.
An IBAction is used to "advertise" a method in your code that should be called when a certain event takes place. For instance, if a button is pushed, or a field updated, you will probably want your application to take action and react appropriately. When you've written a method that implements your event-driven logic, you can declare it with IBAction in the header file, which subsequently will expose it to Interface Builder.
For instance, a method doCalculation might be declared like this:
Notice that the declaration includes a sender parameter with the type of id. This is a generic type that can be used when you don't know (or need to know) the type of object you'll be working with. By using id, you can write code that doesn't tie itself to a specific class, making it easier to adapt to different situations.
When creating a method that will be used as an action (like our doCalculation example), you can identify and interact with the object that invoked the action through the sender variable (or whatever you decide to call it in your code). This will be handy if you decide to design a method that handles multiple different events, such as button presses from several different buttons.
Let me get right to the point. For many of the exercises we'll be doing in this book, a separate data model is not needed; the data requirements are handled within the controller. This is one of the trade-offs of small projects like the one you'll be working through in a few minutes. Although it would be ideal to represent a complete MVC application architecture, sometimes it just isn't possible in the space and time available. In your own projects, you'll need to decide whether to implement a standalone model. In the case of small utility apps, you may find that you rarely need to consider a data model beyond the logic you code into the controller.
As you grow more experienced with the iPhone Software Development Kit (SDK) and start building data-rich applications, you'll want to begin exploring Core Data. Core Data abstracts the interactions between your application and an underlying data-store. It also includes a modeling tool, like Interface Builder, that helps you design your application, but rather than visually laying out interfaces, you can use it to visually map a data structure, as shown in Figure 6.2.
Figure 6.2 Once you become more familiar with iPhone development, you'll want to explore the Core Data tools for managing your data model.
For our beginning tutorials, using Core Data would be like using a sledgehammer to drive a thumbtack. We'll take a closer look at its capabilities in Hour 16, "Reading and Writing Data." Right now, let's get started building your first app with a view and a view controller!