Read iOS Programming: The Big Nerd Ranch Guide, 3/e (Big Nerd Ranch Guides) Online
Authors: Aaron Hillegass,Joe Conway
Tags: #COM051370, #Big Nerd Ranch Guides, #iPhone / iPad Programming
Notice the
???
is now centered in the bottom label. Now center the text in the top label. (There’s no text now, but there will be in the running application.)
Your application’s interface now looks like it should, but before we start writing code, let’s dive into some programming theory.
You may hear iOS programmers mention the Model-View-Controller pattern. What this means is every object you create is exactly one of the following: a model object, a view object, or a controller object.
View objects
are visible to the user. In
Quiz
, the buttons, labels, and the view they are placed on top of are all view objects. Views are usually standard
UIView
subclasses (
UIButton
,
UISlider
), but you will sometimes write custom view classes. These typically have names like
DangerMeterView
or
IncomeGraphView
.
Model objects
hold data and know nothing about the user interface. In this application, the model objects will be two lists of strings: the
questions
array and the
answers
array.
Figure 1.10
displays the object diagram of the
Quiz
application’s model objects.
Figure 1.10 Diagram of model objects in Quiz
Model objects typically use standard collection classes (
NSArray
,
NSDictionary
,
NSSet
) and standard value types (
NSString
,
NSDate
,
NSNumber
). But there can be custom classes, which typically have names that sound like data-bearing objects, such as
InsurancePolicy
or
PlayerHistory
.
View and model objects are the factory workers of an application – they focus tightly on specific tasks. For example, an instance of
UILabel
(a view object) knows how to display text in a given font within a given rectangle. An
NSString
instance (a model object) knows how to store a character string. But the label doesn’t know
what
text it should display, and the string doesn’t know
what
characters it should store.
This is where
controller objects
come in. Controllers are the managers in an application. They keep the view and model objects in sync, control the
“
flow
”
of the application, and save the model objects out to the filesystem (
Figure 1.11
). Controllers are the least reusable classes that you will write, and they tend to have names like
ScheduleController
and
ScoreViewController
.
Figure 1.11 MVC pattern
When you create a new iOS project from a template, the template automatically makes a controller object for you. For
Quiz
, this controller is the
QuizViewController
. Most applications have more than one controller object, but a simple application like
Quiz
only needs one. (Actually, the template creates another controller for
Quiz
– the
QuizAppDelegate
. Every iOS application has an
“
app delegate
”
object, and it is the primary controller of the application. However, to keep things simple, we won’t use the app delegate until
Chapter 6
.)
One of the
QuizViewController
’s tasks will be showing the user a new question when the
Show Question
button is tapped. Tapping this button will trigger a method in the
QuizViewController
. This method will retrieve a new question from an array of questions and place that question in the top label. These interactions are laid out in the object diagram for
Quiz
shown in
Figure 1.12
.
Figure 1.12 Object diagram for Quiz
This diagram is the big picture of
Quiz
. It’s okay if it doesn’t make perfect sense yet; it will make more by the end of the chapter.
To manage its relationships and responsibilities, the
QuizViewController
object needs five instance variables and two methods. In this section, you will declare these in the
QuizViewController
header file,
QuizViewController.h
.
Here are the five instance variables
QuizViewController
needs:
questions
a pointer to an
NSMutableArray
containing instances of
NSString
answers
a pointer to another
NSMutableArray
containing instances of
NSString
currentQuestionIndex
an
int
that holds the index of the current question in the
questions
array
questionField
a pointer to the
UILabel
object where the current question will be displayed
answerField
a pointer to the
UILabel
object where the current answer will be displayed
In the project navigator, select
QuizViewController.h
to open the file in the editor. Add the following code: a set of curly brackets and, inside the brackets, the declarations for the five instance variables. Notice the bold type? In this book, code that you need to add is always bold; the code that’s not bold is there to tell you where to type in the new stuff.
(Scary syntax? Feelings of dismay? Don’t panic – you will learn more about the Objective-C language in the next chapter. For now, just keep going.)
Each of the buttons needs to trigger a method in the
QuizViewController
. A method is a lot like a function – a list of instructions to be executed. Declare two methods in
QuizViewController.h
. Add this code after the curly brackets and before the
@end
.
Save
QuizViewController.h
.
What do
IBOutlet
and
IBAction
do in the declarations you just entered? They allow you to connect your controller and your view objects in the XIB file.
A
connection
lets one object know where another object is in memory so that the two objects can work together. When the
Quiz
application loads
QuizViewController.xib
, the view objects that make up the interface and the
QuizViewController
have no idea how to reach each other. The
QuizViewController
needs to know where the labels are in memory so that it can tell them what to display. The buttons need to know where the
QuizViewController
is so that they can report when they are tapped. Your objects need
connections
.
Figure 1.13
shows the connections for
Quiz
. Some have already been made by the template (between the
view
outlet of
QuizViewController
and the
UIView
instance, for example), and some were made implicitly (dragging objects onto the view object in the XIB file set up connections between the view and the buttons and labels). However, you still have a few more connections to make to get your objects communicating properly.
Figure 1.13 Current connections and needed connections
Here are the missing connections:
Let’s start with the connections to the
UILabel
instances. The instance of
QuizViewController
has a pointer called
questionField
. You want
questionField
to point to the instance of
UILabel
at the top of the view.
Select
QuizViewController.xib
in the project navigator to reopen it. In the outline view, find the
File's Owner
object (which is standing in for the
QuizViewController
). Right-click or Control-click on the
File's Owner
to bring up the connections panel (
Figure 1.14
). Then drag from the circle beside
questionField
to the
UILabel
.
Figure 1.14 Setting questionField
(If you do not see
questionField
here, double-check your
QuizViewController.h
file for typos. Did you end each line with a semicolon? Have you saved the file since you added
questionField
?)
Now when this XIB file is loaded when the application launches, the
QuizViewController
’s
questionField
pointer will automatically point to this instance of
UILabel
. This will allow the
QuizViewController
to talk to the label it calls
questionField
. This is the label on top of the screen.
Next, drag from the circle beside
answerField
to the other
UILabel
(
Figure 1.15
).
Figure 1.15 Setting answerField
Notice that you drag
from
the object with the pointer
to
the object that you want that pointer to point at. Also, notice that the pointers that appear in the connections panel are the ones that you decorated with
IBOutlet
in
QuizViewController.h
.
When a
UIButton
is tapped, it sends a message to another object. The object that is sent the message is called the
target
. The message is called the
action
, and it is the name of the method that tapping the button should trigger. So the button needs answers to two questions:
“
Who’s the target?
”
and
“
What’s the action?
”
For the
Show Question
button, we want the target to be
QuizViewController
and the action to be
showQuestion:
.
To set an object’s target and action, you Control-drag
from
the object
to
its target. When you release the mouse, the target is set, and a pop-up menu appears that lets you choose the action. Select the
Show Question
button and Control-drag (or right-drag) to the
File's Owner
(
QuizViewController
). Once
File's Owner
is highlighted, release the mouse button and choose
showQuestion:
from the pop-up menu, as shown in
Figure 1.16
. Notice that the choices in this menu are the methods you decorated with
IBAction
in
QuizViewController.h
.
Figure 1.16 Setting Show Question target/action
Now set the target and action of the
Show Answer
button. Select the button and Control-drag
from
the button
to
the
File's Owner
. Then choose
showAnswer:
from the pop-up menu (
Figure 1.17
).
Figure 1.17 Setting Show Answer target/action
There are now five connections between your
QuizViewController
and other objects. You’ve set the pointers
answerField
and
questionField
to point at the labels. That’s two. The
QuizViewController
is the target for both buttons. That’s four. The project’s template made one additional connection: the
view
outlet of
QuizViewController
is connected to the
View
object that represents the background of the application. That makes five.
You can check these connections in the
connections inspector
. Select the
File's Owner
in the outline view and then click the
icon in the inspector selector to reveal the connections inspector in the utilities area. (
Figure 1.18
).
Figure 1.18 Checking connections in the Inspector
Your XIB file is complete. The view objects have been created and configured, and all the necessary connections have been made to the controller object. Save your XIB file, and let’s move on to writing methods.