Hour 6. Model-View-Controller Application Design

,

What You’ll Learn in This Hour:

Image What the Model-View-Controller design pattern means

Image Ways in which Xcode implements MVC

Image Design of a basic view

Image Implementation of a corresponding view controller


You’ve come a long way in the past few hours: You’ve provisioned your iDevice for development, learned the basics of the Objective-C language, explored Cocoa Touch, and gotten a feel for Xcode and the Interface Builder (IB) editor. Although you’ve already used a few prebuilt projects, you have yet to build one from scratch. That’s about to change.

In this hour, you learn about the Model-View-Controller application design pattern and create an iOS application from start to finish.

Understanding the Model-View-Controller Design Pattern

When you start programming, you’ll quickly come to the conclusion that there is more than one “correct” way to do just about everything. Part of the joy of programming is that it is a creative process in which you can be as clever as your imagination allows. This doesn’t mean, however, that adding structure to the development process is a bad idea. Having a defined and documented structure means that other developers can work with your code, projects large and small are easy to navigate, and you can reuse your best work in multiple applications.

The application design approach that you’ll be using in iOS is known as Model-View-Controller (MVC), and it can help you create clean, efficient applications.


Note

In Hour 3, “Discovering Objective-C: The Language of Apple Platforms,” you learned about object-oriented (OO) programming and the reusability that it can provide. OO programs, however, can still be poorly structured—and therefore the need to define an overall application architecture that can guide the OO implementation.


Making Spaghetti

Before we get into MVC, let’s first talk about the development practice that we want to avoid, and why. When creating an application that interacts with a user, several things must be taken into account. First, the user interface (UI). You must present something that the user interacts with: buttons, fields, and so on. Second, handling and reacting to the user input. And third, the application must store the information necessary to correctly react to the user (often in the form of a database).

One approach to incorporating all these pieces is to combine them into a single class. The code that displays the interface is mixed with the code that implements the logic and the code that handles data. This can be a straightforward development methodology, but it limits the developer in several ways:

Image When code is mixed together, it is difficult for multiple developers to work together because no clear division exists between any of the functional units.

Image The interface, application logic, and data are unlikely to be reusable in other applications because the combination of the three is too specific to the current project to be useful elsewhere.

Image In short, mixing code, logic, and data leads to a mess. This is known as spaghetti code and is the exact opposite of what we want for our iOS applications. MVC to the rescue!

Structured Application Design with MVC

MVC defines a clean separation between the critical components of our apps. Consistent with its name, MVC defines three parts of an application:

Image A model provides the underlying data and methods that offer information to the rest of the application. The model does not define how the application will look or how it will act.

Image One or more views make up the UI. A view consists of the different onscreen widgets (buttons, fields, switches, and so forth) that a user can interact with.

Image The logical isolation created between the functional parts of an application, illustrated in Figure 6.1, means the code becomes more easily maintainable, reusable, and extendable—the exact opposite of spaghetti code.

Image

FIGURE 6.1 MVC design isolates the functional components of an app.

Unfortunately, MVC comes as an afterthought in many application development environments. When suggesting MVC design, I am often asked, “How do I do that?” This isn’t indicative of a misunderstanding of what MVC is or how it works, but a lack of a clear means of implementing it.

In Xcode, MVC design is natural. As you create new projects and start coding, you are guided into using MVC design patterns automatically. It actually becomes more difficult to program poorly than it does to build a well-structured app.

How Xcode Implements MVC

Over the past few hours, you’ve learned about Xcode and the IB editor and have gotten a sense for how you will use them to write code and design interfaces. In Hour 5, “Exploring Interface Builder,” you even connected storyboard scene objects to the corresponding 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

Views, although possible to create programmatically, are most often designed visually with IB. Views can consist of many different interface elements, the most common of which we covered in Hour 4, “Inside Cocoa Touch.” 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 specific types of information. A toggle-switch outlet, for example, provides access to data that describes whether the switch is on or off. An action, in contrast, defines a method in your application that can be triggered via an event within a view, such as a touch of a button or swiping your finger across the screen.

So, how do outlets and actions connect to code? In the preceding hour, you learned to Control-drag in IB to create a connection, but IB “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 that implement the view’s logic (that is, the controller).


Caution: The Relationship Between Views, Scenes, and Storyboards

At this point, it might seem logical to assume that a storyboard’s scene and a view are the same thing. This isn’t quite true. A scene is used to visually describe a view; it also references a corresponding controller for the view.

Put another way, a scene is where you go to edit a view and assign a controller to it. Storyboards are the files that contain all the scenes you will use in a project.


View Controllers

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, are added to your project’s code. IBAction and IBOutlet are markers that IB recognizes; they serve no other purpose within Objective-C. You add these directives to the interface files of your view controller either manually or using a special feature of IB to generate the code automatically.


Note

View controllers can hold application logic, but I don’t mean to imply that all your code should be within a view controller. Although this is largely the convention for the tutorials in this book, as you create your own apps you can certainly define additional classes to abstract your application logic as you see fit.


Using IBOutlet

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 create an instance variable and property for the label under the name myLabel within your view controller, you could explicitly declare both, or you might use the @property directive alone to implicitly declare the instance variable and add a corresponding property:

@property (weak, nonatomic) UILabel *myLabel;

This gives your application a place to store the reference to the text label and a property to access it with, but it still doesn’t provide a way to connect it to the label in the interface. To do this, you include the IBOutlet keyword as part of the property declaration:

@property (weak, nonatomic) IBOutlet UILabel *myLabel;

Once IBOutlet is added, IB enables you to visually connect the view’s label object to the myLabel variable and property. Your code can then use the property to fully interact with the onscreen label object—changing the label’s text, calling its methods, and so on.

That’s it. That line takes care of instance variable, property, and outlet—and is the pattern we will follow throughout the book.

Using IBAction

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 interface file, which subsequently exposes it to the IB editor. Declaring a method in the interface file, before it is actually implemented, is called prototyping the method.

For instance, a prototype for the method doCalculation might look like this:

-(IBAction)doCalculation:(id)sender;

Notice that the prototype 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 prove handy if you decide to design a method that handles multiple different events, such as button presses from several different buttons.

Data Models

Let me get this out of the way upfront: For many of the exercises 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 must 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 iOS development 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 datastore. It also includes an Xcode data modeling tool, like IB, that helps you design your application, but instead of visually laying out interfaces, you can use it to visually map a data structure, as shown in Figure 6.2.

Image

FIGURE 6.2 After you become more familiar with iOS development, you might 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. Right now, let’s get started building your first app with a view and a view controller.

Using the Single View Application Template

The easiest way to see how Xcode manages to separate logic from display is to build an application that follows this approach. Apple has included a useful application template in Xcode that quickly sets up a project with a storyboard, an empty view, and an associated view controller. This Single View Application template will be the starting point for many of your projects, so the rest of this hour you learn how to use it.

Implementation Overview

The project we’ll build is simple: Instead of just writing the typical Hello World app, we want to be a bit more flexible. The program presents the user with a field (UITextField) for typing and a button (UIButton). When the user types into the field and presses the button, the display updates an onscreen label (UILabel) so that the word Hello is shown, followed by the user’s input. The completed HelloNoun, as I’ve chosen to call this project, is shown in Figure 6.3.

Image

FIGURE 6.3 The app accepts input and updates the display based on what the user types.

Although this won’t be a masterpiece of development, it does contain almost all the different elements we discuss in this hour: a view, a controller, outlets, and actions. Because this is the first full development cycle that we’ve worked through, we’ll pay close attention to how all the pieces come together and why things work the way they do.

Setting Up the Project

First we want to create the project, which we’ll call HelloNoun, in Xcode:

1. Launch Xcode from the Applications folder or Launchpad.

2. Choose File, New, Project.

3. You are prompted to choose a project type and a template. On the left side of the New Project window, make sure that Application is selected under the iOS project type. Select the Single View Application option from the icons on the right, and then click Next.

4. Type HelloNoun in the Product Name field. Use your full name for the organization name. For the company identifier, enter a domain to represent yourself, in reverse order. (I’m using com.teachyourselfios; refer to the “Creating and Managing Projects” section in Hour 2, “Introduction to Xcode and the iOS Simulator,” for more information.) Leave Class Prefix blank, and be sure that Device Family is set to either iPhone or iPad, as shown in Figure 6.4, and then click Next.

Image

FIGURE 6.4 Choose the name and target device for your application.

5. Choose a save location when prompted and uncheck Create git Repository. Do not add the new project to an existing project or workspace, if asked. Click Create to generate the project.

This creates a simple application structure consisting of an application delegate, a window, a view (defined in a storyboard scene), and a view controller. After a few seconds, your project window will open (see Figure 6.5).

Image

FIGURE 6.5 The workspace for your new project.

Class Files

If it isn’t already visible, open the top-level project code group (named HelloNoun) and review the contents. You should see five files (shown in Figure 6.5): AppDelegate.h, AppDelegate.m, ViewController.h, ViewController.m, and Main.storyboard.

The AppDelegate.h and AppDelegate.m files make up the delegate for the instance of UIApplication that this project will create. In other words, these files can be edited to include methods that govern how the application behaves when it is running. You modify the delegate when you want to perform application-wide setup operations at launch or when you want to tell an application how to behave when it moves into the background (or becomes the foreground application again), or when you want to choose what to do when an application is forced to quit. For this project, you do not need to edit anything in the application delegate; but keep in mind the role that it plays in the overall application life cycle.

The second set of files, ViewController.h and ViewController.m, implements the class that contains the logic for controlling our view: a view controller (UIViewController). These files are largely empty to begin, with just a basic structure in place to ensure that we can build and run the project from the outset. In fact, feel free to click the Run button at the top of the Xcode window. The application will compile and launch, but there won’t be anything to do.


Note

If you provide a “class prefix” when creating a project in Xcode, all the class filenames are prefixed with the text you enter. In earlier versions of Xcode, Apple used the name of the application itself as the class prefix.


To impart some functionality to this app, we need to work on the two areas discussed previously: the view and the view controller.

The Storyboard File

In addition to the class files, the project contains a storyboard file that will store the interface design. Click the Main.storyboard file to open it in the IB editor, and then expand the objects in the document outline. Shown in Figure 6.6, Main.storyboard contains icons for the First Responder (an instance of UIResponder), the View Controller (our ViewController class), and our application’s View (an instance of UIView). There are also icons for the Top and Bottom “layout guides”; these are tools you’ll learn about later to help lay out and align your UI. The view controller and first responder are also visible in the bar underneath the view in the editor. Remember from Hour 5 that if you don’t see the icons in the bar, just click it and they’ll appear.

Image

FIGURE 6.6 When the storyboard file is loaded, the application’s view controller and initial view are instantiated.

As you learned earlier, when a storyboard file is loaded by an app, the objects within it are instantiated, meaning they become real, active parts of the application. In the case of HelloNoun (and any other application based on the Single View Application template), when the application launches, a window is created, Main.storyboard is loaded, along with an instance of the ViewController class and its view, which is added to the window.

Reasonable persons are probably scratching their heads right now wondering a few things. For example, how does Main.storyboard get loaded at all? Where is the code to tell the application to do this?

The Main.storyboard file is defined in the HelloNoun-Info.plist file as the property value for the key Main storyboard file base name. You can see this yourself by opening the Supporting Files group and then clicking the plist file to show the contents. Alternatively, just click the top-level project icon, make sure the HelloNoun target is selected, and view the Main Interface field in the General section (see Figure 6.7).

Image

FIGURE 6.7 The project’s plist file defines the storyboard loaded when the application starts.

Okay, so that explains how the storyboard file gets loaded, but how does it know to load the scene? If you recall, a storyboard can have multiple scenes. So, because this is a single-view application, is it just loading the only scene it can? What happens when there are multiple scenes? All good questions.

In typical Apple style, the initial scene (and corresponding view controller/view) is chosen rather subtly in the IB editor itself. Refer back to Figure 6.6. See the gray arrow in the editor area that points to the left side of the view? That arrow is draggable and, when there are multiple different scenes, you can drag it to point to the view corresponding to any scene. This action automatically configures the project to launch that scene’s view controller and view when the application launches.

In summary, the application is configured to load Main.storyboard, which looks for the initial scene and then creates an instance of that scene’s view controller class (ViewController, as defined in the ViewController.h and ViewController.m files). The view controller loads its view, which is added automatically to the main window. If that still doesn’t make sense, don’t fret; I guide you through this every step of the way.


Note

I’ve mentioned “window” a few times in this discussion. In iOS development, your application has a window that covers the screen and is created when it loads. Views are then displayed within this window. The window is referenced through the property window in the application delegate class. Because your initial view is automatically displayed in the window when the application starts, you’ll rarely need to interact with it directly.


Planning the Properties and Connections

The first step of building our project is to decide on all the things our view controller needs to make it work. What instance variables do we need to reference objects that we’re going to use? What properties should we define to safely access the instance variables? Finally, what outlets do we need to provide for the view to connect to our variables, and what actions will our interface trigger?

For this simple project, we must interact with three different objects:

Image A text field (UITextField)

Image A label (UILabel)

Image The first two provide input (the field) and output (the label) for the user. The third (the button) triggers an action in our code to set the contents of the label to the contents of the text field.

Setting Up a View Controller Interface Block

Based on what we now know, we could edit the @interface block at the top of ViewController.m to define the instance variables we need to reference interface elements and the properties (with outlets) that we’ll use to manipulate them.

We’ll name the field (UITextField) that collects user input, userInput, and the label (UILabel) that provides output will be userOutput. Recall that we can use the @property directive to create the instance variables and properties all at once and add the IBOutlet keyword to make the connection between the interface and code.

This boils down to two lines:

@property (weak, nonatomic) IBOutlet UILabel *userOutput;
@property (weak, nonatomic) IBOutlet UITextField *userInput;

To finish the @interface block, we also need to include the action that is performed when the button is pressed. We will name this setOutput:

- (IBAction)setOutput:(id)sender;

All of this, put into context, results in a block of code at the top of the ViewController.m file that resembles this (bold lines show what was added):

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *userOutput;
@property (weak, nonatomic) IBOutlet UITextField *userInput;
- (IBAction)setOutput:(id)sender;
@end

Note that these lines would be added to the implementation file (ViewController.m) because none of these items need to be shared outside of ViewController.m. This means that userOutput and userInput would be considered private properties, and setOutput a private method. Because nothing is being shared with another class, the interface file (ViewController.h) won’t change at all!

That’s all we’d need to do. We could then connect our interface to code, just as we did in the last hour, and implement setOutput in ViewController.m.


Caution: Stop! Don’t Type a Thing

Notice that I’ve been saying we could and we would rather than directing you to start typing? That’s because now that you understand how the code could be set up by hand, I’ll show you how Xcode can automate the process for you.

Some developers prefer to set up outlets, properties, and such manually. You’re welcome to do this, but you’re about to learn that Xcode can generate the same code for you, with almost no typing.



Note

If you’re skimming through the HelloNoun code files, you may notice that there are green comments (lines that start with the characters //). These are usually left out of the code listings in the book to save space.


A Simplified Approach

Although you still haven’t typed any code, what I’m hoping you’ve learned over the past few minutes is that a successful project begins with a successful planning and setup process. So, you want to do the following:

Image Identify your instance variables. What values or objects will you need to exist through the life of a class (frequently a view controller)?

Image Identify your outlets and actions. Which instance variables need to be connected to an object defined in your interface, and what methods will be triggered by the interface?

Image Create corresponding properties. For any instance variable that you want to manipulate, you should use a property declaration to define both the instance variable and property. If the property represents an object in your interface, it must include the IBOutlet keyboard as part of its declaration.

You’ve seen that this can be performed manually, but what if Xcode could do all the work for you? What if the IB editor, through the very process of making the connections that you learned about in Hour 5, could add property directives, create interface outlets and actions, and insert the empty (skeleton) methods for the actions into your implementation file? It can!

While the core basis of binding views to view controllers still relies on the code you’ve just seen, you can use Xcode to automatically write it for you as you build your interface. You still want to identify the instance variables/properties, outlets, and actions you want to create before starting the interface, and you’ll still sometimes need to do a bit of additional code setup beforehand, but allowing Xcode to generate code automatically dramatically speeds up the initial stages of development.

Now, without further ado, let’s build our application.

Designing the Interface

You’ve seen that IB makes designing a user interface (UI) as much fun as playing around in your favorite graphics application. That said, our emphasis is on the fundamentals of the development process and the objects we have at our disposal. Where it isn’t critical, we move quickly through the interface creation.

Adding the Objects

The interface for the HelloNoun application is quite simple: It must provide a space for output, a field for input, and a button to set the output to the same thing as the input. Follow these steps to create the UI:

1. Open Main.storyboard by selecting it within the Xcode project navigator.

2. The IB editor opens the file, displaying the view controller scene objects in the document outline, and a visual representation of the scene’s view in the editor.

3. Make sure that the Object Library is open on the right by choosing View, Utilities, Show Object Library (Control-Option-Command-3). Verify that the Objects button is selected within the library; this displays all the components that we can drag into the view. Your workspace should now resemble Figure 6.8.

Image

FIGURE 6.8 Open the view and the Object Library to begin creating the interface.v

4. Add two labels to the view by clicking and dragging the label (UILabel) object from the Object Library into the view.

5. The first label is just static text that says Hello. Double-click the default text that reads Label to edit it and change the content to read Hello. Position the second label underneath it; this will act as the output area.

For this example, I changed the text of the second label to read <Noun Goes Here!>. This will serve as a default value until the user provides a new string. You might need to expand the text labels by clicking and dragging their handles to create enough room for them to display.

I also chose to set my labels to align their text to the center. If you want to do the same, select the label within the view by clicking it and then press Option-Command-4 or click the Attributes Inspector icon (a slider) at the top of the Xcode utility area. This opens the Attributes Inspector for the label.

Use the alignment buttons to change the default text alignment for the labels. You may also explore the other attributes to see the effect on the text, such as size, shadow, color, and so on. Your view should contain two labels and resemble Figure 6.9.

Image

FIGURE 6.9 Use the Attributes Inspector to set the labels’ text alignment to center and to increase the font size.

6. When you’re happy with the results, it’s time to add the elements that the user will be interacting with: the text field and button. Find the Text Field object (UITextField) within the Object Library and click and drag to position it under your two labels. Using the handles on the field, stretch it so that it matches the length of your output label.

7. Open the Attributes Inspector again (Option-Command-4) and set the text size to match the labels you added earlier, if desired. Notice that the field itself doesn’t get any bigger. This is because the default field type on the iPhone has a set height. To change the height, you can click one of the square Border Style buttons in the Attributes Inspector. The field then allows you to resize its height freely.

8. Finally, click and drag a Button (UIButton) from the Object Library into the view, positioning it right below the text field. Double-click in the center of the button to add a title, such as Set Label. Resize the button to fit the label, if needed. You may also want to again use the Attributes Inspector to increase the font size. Figure 6.10 shows my version of the finished view.

Image

FIGURE 6.10 Your interface should include four objects (two labels, a field, and a button), just like this.

Creating and Connecting the Outlets and Actions

Our work in IB is almost complete. The last remaining step is to connect the view to the view controller. If we had defined manually the outlets and actions as described earlier, this would be a matter of dragging from one object icon to another. As it turns out, even though we’re going to be creating the outlet and action code on-the-fly, it’s still just a matter of drag and drop.

To do this, we need to be able to drag from the IB editor to the area of the code where we want to add an outlet or an action. In other words, we need to be able to see the ViewController.m file at the same time we see the view that we are connecting. This is a great time to use the assistant editor feature of Xcode.

With your completed interface visible in the IB editor, click the Assistant Editor button (the middle button in the Editor section of the toolbar). The ViewController.m file automatically opens to the right of the interface because Xcode knows that when you connect interface elements to code, they should be through private properties in your implementation (.m) file.

If Xcode opens the wrong file instead (sometimes it can be finicky), just click the name of the file directly above the editing area, and you’ll see a menu where you can select the other files in the project.

At this point, you might be noticing a problem: If you’re on a small MacBook, or editing an iPad version of the project, you’re running out of screen space. To conserve space, use the leftmost and rightmost “view” buttons on the toolbar to disable the navigation and utility areas of the Xcode window. You can also use the disclosure arrow in the lower-left corner of IB editor itself to toggle the document outline off. Your screen should now resemble Figure 6.11.

Image

FIGURE 6.11 Turn on the assistant editor and make room in your workspace.

Adding the Outlets

We’ll start by connecting the label we created for user output. Recall that we want this to be represented by an instance variable and corresponding property called userOutput:

1. Control-drag from the label that you’ve established for output (titled <Noun Goes Here!> in the example) or its icon in the document outline. Drag all the way into the code editor for ViewController.m, releasing the mouse button when your cursor is just under the @interface line. As you drag, you see a visual indication of what Xcode is planning to insert when you release the button, as shown in Figure 6.12.

Image

FIGURE 6.12 Choose where your connection code will be generated.

2. When you release the mouse button, you are prompted to define an outlet. Be sure that the Connection menu is set to Outlet, Storage is Weak, and the type is set to UILabel (because that’s what the object is). Finally, specify the name you want to use for the property (userOutput), and then click Connect, as shown in Figure 6.13.

Image

FIGURE 6.13 Configure the specifics of the outlet you’re creating.

3. When you click Connect, Xcode automatically inserts the proper @property directive with IBOutlet (implicitly declaring the instance variable). What’s more, it has made the connection between the outlet you just defined and the code itself. If you want to verify this, just check the Connections Inspector or right-click the field to open the Quick Inspector, as you learned in Hour 5.

4. Repeat the process for the text field, dragging it to just below the @property line that was inserted. This time, choose UITextField as the type and userInput as the name of the outlet.


Caution: Watch Where You Drag

Placing your first connection is easy, but you must target the right part of the code in subsequent drags. It is critically important that you drag subsequent interface objects that you want to define in your code to an area below the @property lines that Xcode adds.

If you don’t, Xcode may insert only an instance variable, and all the supporting code for a property will be missing. If this happens, undo and try again.


With those few steps, you’ve created and inserted the proper code to support the input and output view objects, and the connections to the view controller are now established. To finish the view, however, you still must define a setOutput action and connect the button to it.

Adding the Action

Adding the action and making the connection between the button and the action follows the same pattern as the two outlets you just added. The only difference is that actions are usually defined after properties in an interface file, so you’ll just be dragging to a slightly different location.

1. Control-drag from the button in the view to the @interface block in ViewController.m, just below the two @property directives that you automatically added earlier. Again, as you drag, you’ll see Xcode provide visual feedback about where it is going to insert code. Release the mouse button when you’ve targeted the line where you want the action code to be inserted.

2. As with the outlets, you are prompted to configure the connection, as demonstrated in Figure 6.14. This time, be sure to choose Action as the connection type; otherwise, Xcode tries to insert another outlet. Set the Name to setOutput (the method name we chose earlier). Be sure that the Event pop-up menu is set to Touch Up Inside to configure the event that will trigger the action. Leave the rest of the fields set to their defaults and click Connect.

Image

FIGURE 6.14 Configure the action that will be inserted into the code.

You’ve just added the instance variables, properties, outlets, and actions, and connected them all to your code.

Go ahead and reconfigure your Xcode workspace to use the standard editor and make sure that the project navigator is visible before continuing. If you want to double-check your work, review the contents of the ViewController.m make sure the @interface block matches the code described earlier in this hour.

Implementing the Application Logic

With the view complete and the connection to the view controller in place, the only task left is to fill in the logic. Let’s turn our attention back toward the ViewController.m file and the implementation of setOutput.

The purpose of the setOutput method is to set the output label to the contents of the field that the user edited. How do we get/set these values? Simple. Both UILabel and UITextField classes have a property called text that contains their contents. By reading and writing to these properties, we can set userInput to userOutput in one easy step.

Open ViewController.m and scroll to the bottom. You’ll find one more treat the Xcode gives us when it creates action connection code. It also writes an empty method definition (in this case, setOutput), just waiting for us to fill it in. Find the method, and then insert the bolded line to make it read as shown in Listing 6.1.

LISTING 6.1 Completed setOutput Method


- (IBAction)setOutput:(id)sender {
    self.userOutput.text=self.userInput.text;
}


It all boils down to a single line. This single assignment statement does everything we need. Well done! You’ve written your first iOS application.


Note

In this example (and most examples throughout this book), I use the nifty dot notation (self.userInput.text, for example) to get and set information. We could also have implemented the setOutput logic like this:

[[self userOutput] setText:[[self userInput] text]];

Either way is fine technically, but you should always code for readability and ease of maintenance. Which do you think is easier to understand?


Building the Application

The app is ready to build and test. If you want to deploy to your iOS device, be sure it is connected and ready to go. Select your device or the iOS Simulator from the Scheme menu on the Xcode toolbar, and then click Run.

After a few seconds, the application starts on your iDevice or within the Simulator window, as shown in Figure 6.15.

Image

FIGURE 6.15 Your finished application makes use of a view to handle the UI and a view controller to implement the functional logic.


Caution: Quitting Applications

After you’re done running an application, use the Stop button on the Xcode toolbar to exit it. If you use the Home button in the iOS Simulator, the application will move to the background and Xcode may get a bit confused. If this happens, you can double-click the iOS Simulator’s Home button to access the task manager and manually stop the application (just like a real iOS device).


Further Exploration

Before moving on to subsequent hours, you may want to learn more about how Apple has implemented the MVC design versus other development environments that you may have used. An excellent document titled Cocoa Design Patterns provides an in-depth discussion of MVC as applied to Cocoa. You can find and read this introduction by searching for the title in the Xcode documentation system, which we discussed in Hour 4.

You might also want to take a breather and use the finished HelloNoun application as a playground for experimentation. We discussed only a few of the different IB attributes that can be set for labels, but dozens more can customize the way that fields and buttons display. The flexibility of the view creation in IB goes well beyond what can fit in one book, so exploration is necessary to take full advantage of the tools. This is an excellent opportunity to play around with the tools and see the results, before we move into more complex (and easy-to-break) applications.

Summary

In this hour, you learned about the MVC design pattern and how it separates the display (view), logic (controller), and data (model) components of an application. You also explored how Apple implements this design within Xcode through the use of Core Data, views, and view controllers. This approach will guide your applications through much of this book and in your own real-world application design, so learning the basics now will pay off later.

To reinforce the lesson, we worked through a simple application using the Single View Application template. This included first identifying the outlets and actions that would be needed and then using Xcode to create them. Although not the most complex app you’ll write, it included the elements of a fully interactive user experience: input, output, and (very simple) logic.

Q&A

Q. I don’t like the idea of code being written without seeing it. Should I create actions and outlets myself?

A. That is entirely up to the developer. The code-generation features in Xcode are still relatively new and can be a bit touchy. As long as you understand how to set up a project manually, I suggest that you use the Xcode tools to do the work but review the code it creates immediately afterward.

Q. I noticed some circles displayed beside code lines in the interface and implementation files. What are those?

A. These are yet another way to connect your interface to code. If you manually define the outlets and actions, circles appear beside potential connection points in your code. You can then Control-drag from your interface objects to the circles to make connections. What’s more, clicking these circles after connections are in place will display the endpoint of the connection.

Workshop

Quiz

1. What event do you use to detect a button tap?

2. What purpose does the @property directive serve?

3. Which Apple project template creates a simple view/view controller application?

4. What is the relationship between storyboards, scenes, views, and view controllers?

Answers

1. The Touch Up Inside event is most commonly used to trigger actions based on a button press.

2. The @property directive defines a property that corresponds to an instance variable. The property gives us a means of accessing our instance variables without having to manipulate them directly. In addition, a property that is declared without a corresponding instance variable automatically generates that instance variable for you. Implicitly created instance variables are named the same as their property, but with an underscore (_) prefix; we (and Apple) take advantage of this feature throughout the book.

3. The Single View Application template is the starting point for many of our apps in this book. It provides a storyboard with a single scene/view and a corresponding view controller (everything a basic app needs).

4. A scene is where you go to edit a view and assign a controller to it. Storyboards are the files that contain all the scenes you will use in a project.

Activities

1. Explore the attributes of the interface objects that you added to the tutorial project in Interface Builder. Try setting different fonts, colors, and layouts. Use these tools to customize the view beyond the simple layout created this hour.

2. Rebuild HelloNoun using outlets, actions, instance variables, and properties that you define and manage manually. Make your connections using the same techniques discussed in the Hour 5 tutorial. This is good practice for getting familiar with what goes on behind the scenes.

3. Review the Apple Xcode documentation for the Core Data features of Cocoa. Although you won’t be using this technology in this book’s tutorials, it is an important tool that you’ll ultimately want to become more familiar with for advanced data-driven applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.157.182