iOS Programming: The Big Nerd Ranch Guide (2014)

1. A Simple iOS Application

In this chapter, you are going to write an iOS application named Quiz. This application will show a question and then reveal the answer when the user taps a button. Tapping another button will show the user a new question (Figure 1.1).

Figure 1.1  Your first application: Quiz

Your first application: Quiz

When you are writing an iOS application, you must answer two basic questions:

·        How do I get my objects created and configured properly? (Example: “I want a button here entitled Show Question.”)

·        How do I deal with user interaction? (Example: “When the user taps the button, I want this piece of code to be executed.”)

Most of this book is dedicated to answering these questions.

As you go through this first chapter, you will probably not understand everything that you are doing, and you may feel ridiculous just going through the motions. But going through the motions is enough for now. Mimicry is a powerful form of learning; it is how you learned to speak, and it is how you will start iOS programming. As you become more capable, you will experiment and challenge yourself to do creative things on the platform. For now, just do what we show you. The details will be explained in later chapters.

Creating an Xcode Project

Open Xcode and, from the File menu, select New → Project...

A new workspace window will appear, and a sheet will slide down from its toolbar. On the lefthand side, find the iOS section and select Application (Figure 1.2). You will be offered several application templates to choose from. Select Empty Application.

Figure 1.2  Creating a project

Creating a project

You are using the Empty Application template because it generates the least amount of boilerplate code. Too much boilerplate gets in the way of learning how things work.

This book was created for Xcode 5.0.2. The names of these templates may change with new Xcode releases. If you do not see an Empty Application template, use the simplest-sounding template. Or visit the Big Nerd Ranch forum for this book at forums.bignerdranch.com for help working with newer versions of Xcode.

Click Next and, in the next sheet, enter Quiz for the Product Name (Figure 1.3). The organization name and company identifier are required to continue. You can use Big Nerd Ranch and com.bignerdranch. Or use your company name and com.yourcompanynamehere.

In the Class Prefix field, enter BNR and, from the pop-up menu labeled Devices, choose iPhone. Make sure that the Use Core Data checkbox is unchecked.

Figure 1.3  Configuring a new project

Configuring a new project

You are creating Quiz as an iPhone application, but it will run on an iPad. It will not look quite right on the iPad’s screen, but that is okay for now. For the first part of this book, you will stick to iPhone applications and focus on learning the fundamentals of the iOS SDK, which are the same across devices. Later, you will see some options for iPad-only applications as well as how to make applications run natively on both types of devices.

Click Next and, in the final sheet, save the project in the directory where you plan to store the exercises in this book. You can uncheck the box that creates a local git repository, but keeping it checked will not hurt anything. Click Create to create the Quiz project.

Once the project is created, it will open in the Xcode workspace window (Figure 1.4).

Figure 1.4  Xcode workspace window

Xcode workspace window

Take a look at the lefthand side of the workspace window. This area is called the navigator area, and it displays different navigators – tools that show you different parts of your project. You can choose which navigator to use by selecting one of the icons in the navigator selector, which is the bar just above the navigator area.

The navigator currently open is the project navigator. The project navigator shows you the files that make up your project (Figure 1.5). You can select a file to open it in the editor area to the right of the navigator area.

The files in the project navigator can be grouped into folders to help you organize your project. A few groups have been created by the template for you; you can rename them whatever you want or add new ones. The groups are purely for the organization of files and do not correlate to the filesystem in any way.

Figure 1.5  Quiz application’s files in the project navigator

Quiz application’s files in the project navigator

In the project navigator, find the files named BNRAppDelegate.h and BNRAppDelegate.m. These are the files for a class named BNRAppDelegate. The Empty Application template created this class for you.

A class describes a kind of object. iOS development is object-oriented, and an iOS application consists primarily of a set of objects working together. When the Quiz application is launched, an object of the BNRAppDelegate kind will be created. We refer to a BNRAppDelegate object as an instanceof the BNRAppDelegate class.

You will learn much more about how classes and objects work in Chapter 2. Right now, you are going to move on to some application design theory and then dive into development.

Model-View-Controller

Model-View-Controller, or MVC, is a design pattern used in iOS development. In MVC, every object is either a model object, a view object, or a controller object.

·         View objects are visible to the user. Examples of view objects are buttons, text fields, and sliders. View objects make up an application’s user interface. In Quiz, the labels showing the question and answer and the buttons beneath them are view objects.

·         Model objects hold data and know nothing about the user interface. In Quiz, the model objects will be two ordered lists of strings: one for questions and another for answers.
Usually, the model objects are modeling real things from the world of the user. For example, when you write an app for an insurance company, you will almost certainly end up with a custom model class called InsurancePolicy.

·         Controller objects are the managers of an application. Controllers configure the views that the user sees and make sure that the view and model objects keep in sync.
In general, controllers typically handle “And then?” questions. For example, when the user selects an item from a list, the controller determines what that user sees next.

Figure 1.6 shows the flow of control in an application in response to user input, such as the user tapping a button.

Figure 1.6  MVC pattern

MVC pattern

Notice that the models and views do not talk to each other directly; controllers sit squarely in the middle of everything, receiving messages from some objects and dispatching instructions to others.

Designing Quiz

You are going to write the Quiz application using the MVC pattern. Here is a break down of the objects you will be creating and working with:

·        4 view objects: two instances of UILabel and two instances of UIButton

·        2 controller objects: an instance of BNRAppDelegate and an instance of BNRQuizViewController

·        2 model objects: two instances of NSMutableArray

These objects and their relationships are laid out in the object diagram for Quiz shown in Figure 1.7.

Figure 1.7  Object diagram for Quiz

Object diagram for Quiz

This diagram is the big picture of how the finished Quiz application will work. For example, when the Show Question button is tapped, it will trigger a method in the BNRQuizViewController. A method is a lot like a function – a list of instructions to be executed. This method will retrieve a new question from the array of questions and ask the top label to display that question.

It is okay if this object diagram does not make sense yet; it will by the end of the chapter. Refer back to it as you continue to see how the app is taking shape.

You are going to build Quiz in steps, starting with the controller object that sits in the middle of the app – BNRQuizViewController.

Creating a View Controller

The BNRAppDelegate class was created for you by the Empty Application template, but you will have to create the BNRQuizViewController class. We will talk more about classes in Chapter 2 and more about view controllers in Chapter 6. For now, just follow along.

From the File menu, select New → File.... A sheet will slide down asking what type of file you would like to create. On the lefthand side under the iOS section, select Cocoa Touch. Then choose Objective-C Class and click Next.

Figure 1.8  Creating an Objective-C class

Creating an Objective-C class

On the next sheet, name the class BNRQuizViewController. For the Subclass of field, click the drop-down menu arrow and select UIViewController. Select the With XIB for user interface checkbox.

Figure 1.9  Creating a view controller

Creating a view controller

Click Next, and a panel will drop down that prompts you to create the files for this new class. When creating a new class for a project, you want to save the files that describe it inside the project’s source directory on the filesystem. By default, the current project directory is already selected for you. You can also choose the group in the project navigator that these files will be added to. Because these groups are simply for organizing and because this project is very small, just stick with the default.

Make sure the checkbox is selected for the Quiz target. This ensures that the BNRQuizViewController class will be compiled when the Quiz project is built. Click Create.

Figure 1.10  Quiz target is selected

Quiz target is selected

Building an Interface

In the project navigator, find the class files for BNRQuizViewController. When you created this class, you checked the box for With XIB for user interface, so BNRQuizViewController came with a third class file: BNRQuizViewController.xib. Find and select BNRQuizViewController.xib in the project navigator to open it in the editor area.

When Xcode opens a XIB (pronounced “zib”) file, it opens it with Interface Builder, a visual tool where you can add and arrange objects to create a graphical user interface. In fact, XIB stands for XML Interface Builder.

In many GUI builders on other platforms, you describe what you want an application to look like and then press a button to generate a bunch of code. Interface Builder is different. It is an object editor: you create and configure objects, like buttons and labels, and then save them into an archive. The archive is the XIB file.

Interface Builder divided the editor area into two sections: the dock is on the lefthand side and the canvas is on the right.

The dock lists the objects in the XIB file either as icons (icon view) or in words (outline view). The icon view is useful when screen real estate is running low. However, for learning purposes, it is easier to see what is going on in the outline view.

If the dock is in icon view, click the disclosure button in the bottom lefthand corner of the canvas to reveal the outline view (Figure 1.11).

Figure 1.11  Editing a XIB file in Interface Builder

Editing a XIB file in Interface Builder

The outline view tells you that BNRQuizViewController.xib contains three objects: two placeholders and a View. Ignore the placeholders for now; you will learn about them later.

The View object is an instance of UIView. This object forms the foundation of your user interface and you can see it displayed on the canvas. The canvas shows how your user interface will appear in the application.

Click on the View object in the document outline to select it in the canvas. You can move the view by dragging it around. Note that moving the view does not change anything about the actual object; it just re-organizes the canvas. You can also close the view by clicking the x in its top left corner. Again, this does not delete the view; it just removes it from the canvas. You can get it back by selecting it in the outline view.

Right now, your interface consists solely of this view object. You need to add four additional view objects for Quiz: two labels and two buttons.

Figure 1.12  Labels and buttons needed

Labels and buttons needed

Creating view objects

To add these view objects, you need to get to the object library in the utility area.

The utility area is to the right of the editor area and has two sections: the inspector and the library. The top section is the inspector, which contains settings for the file or object that is selected in the editor area. The bottom section is the library, which lists items that you can add to a file or project.

At the top of each section is a selector for different types of inspectors and libraries (Figure 1.13). From the library selector, select the Creating view objects tab to reveal the object library.

Figure 1.13  Xcode utility area

Xcode utility area

The object library contains the objects that you can add to a XIB file to compose your interface. Find the Label object. (It may be right at the top; if not, scroll down the list or use the search bar at the bottom of the library.) Select this object in the library and drag it onto the view object on the canvas. Position this label in the center of the view, near the top. Drag a second label onto the view and position it in the center, closer to the bottom.

Next, find Button in the object library and drag two buttons onto the view. Position one below each label.

You have now created four view objects and added them to BNRQuizViewController’s user interface. Confirm this in the document outline.

Configuring view objects

Now that you have created the view objects, you can configure their attributes. Some attributes, like size, position, and text, can be changed directly on the canvas. Others must be changed in the attributes inspector, a tool that you will use shortly.

You can resize an object by selecting it on the canvas or in the outline view and then dragging its corners and edges in the canvas. Resize all four of your view objects to span most of the window.

Figure 1.14  Stretching the labels and buttons

Stretching the labels and buttons

You can edit the title of a button or a label by double-clicking it and typing in new text. Change the top button’s title to Show Question and the bottom button’s title to Show Answer. Change the bottom label to display ???. Delete the text in the top label and leave it blank. (Eventually, this label will display the question to the user.) Your interface should look like Figure 1.15.

Figure 1.15  Setting the text on the labels and buttons

Setting the text on the labels and buttons

It would be nice if the text in the labels was centered. Setting the text alignment of a label must be done in the attributes inspector.

Select the Setting the text on the labels and buttons tab to reveal the attributes inspector. Then select the bottom label on the canvas.

In the attributes inspector, find the segmented control for alignment. Select the centered text option, as shown in Figure 1.16.

Figure 1.16  Centering the label text

Centering the label text

Back on the canvas, notice that the ??? is now centered in the bottom label. Select the top label in the canvas and return to the attributes inspector to set its text alignment. (This label has no text to display now, but it will in the running application.)

To inform the user where they are able to tap, you can change the background color of the buttons. Select the Show Question button on the canvas.

In the attributes inspector, scroll down until you see the attributes under the View header. Next to the Background label, click on the color (the white box with a red slash). This will bring up the full color picker. Pick a nice color to go with the button’s blue text.

Do the same for the second button, but instead of clicking on the color on the left side, click on the right side which has text and the up and down arrows. This will bring up a list of recently used colors in chronological order as well as some system default colors. Use this to choose the same color for the second button’s background color.

NIB files

At this point, you may be wondering how these objects are brought to life when the application is run.

When you build an application that uses a XIB file, the XIB file is compiled into a NIB file that is smaller and easier for the application to parse. Then the NIB file is copied into the application’s bundle. The bundle is a directory containing the application’s executable and any resources the executable uses.

At runtime, the application will read in, or load, the NIB file when its interface is needed. Quiz only has one XIB file and thus will have only one NIB file in its bundle. Quiz’s single NIB file will be loaded when the application first launches. A complex application, however, will have many NIB files that are loaded as they are needed. You will learn more about how NIB files are loaded in Chapter 6.

Your application’s interface now looks like it should. But to begin making it functional, you need to make some connections between these view objects and the BNRQuizViewController that will be running the show.

Making connections

connection lets one object know where another object is in memory so that the two objects can communicate. There are two kinds of connections that you can make in Interface Builder: outlets and actions. An outlet points to an object. (If you are not familiar with “pointers,” you will learn about them in Chapter 2.) An action is a method that gets triggered by a button or some other view that the user can interact with, like a slider or a picker.

Let’s start by creating outlets that point to the instances of UILabel. Time to leave Interface Builder briefly and write some code.

Declaring outlets

In the project navigator, find and select the file named BNRQuizViewController.m. The editor area will change from Interface Builder to Xcode’s code editor.

In BNRQuizViewController.m, delete any code that the template added between the @implementation and @end directives so that the file looks like this:

#import "BNRQuizViewController.h"

@interface BNRQuizViewController ()

@end

@implementation BNRQuizViewController

@end

Next, add the following code. Do not worry about understanding it right now; just get it in.

#import "BNRQuizViewController.h"

@interface BNRQuizViewController ()

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

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

@end

@implementation

@end

Notice the bold type? In this book, code that you need to type in is always bold; the code that is not bold provides context for where to add the new stuff.

In this new code, you declared two properties. You will learn about properties in Chapter 3. For now, focus on the second half of the first line.

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

This code gives every instance of BNRViewController an outlet named questionLabel, which it can use to point to a UILabel object. The IBOutlet keyword tells Xcode that you will set this outlet using Interface Builder.

Setting outlets

In the project navigator, select BNRQuizViewController.xib to reopen Interface Builder.

You want the questionLabel outlet to point to the instance of UILabel at the top of the user interface.

In the dock, find the Placeholders section and the File's Owner object. A placeholder stands in for another object in the running application. In your case, the File's Owner stands in for an instance of BNRQuizViewController, which is the object responsible for managing the interface defined inBNRQuizViewController.xib.

In the dock, right-click or Control-click on the File's Owner to bring up the connections panel (Figure 1.17). Then drag from the circle beside questionLabel to the UILabel. When the label is highlighted, release the mouse button, and the outlet will be set.

Figure 1.17  Setting questionLabel

Setting questionLabel

(If you do not see questionLabel in the connections panel, double-check your BNRQuizViewController.m file for typos.)

Now when the NIB file is loaded, the BNRQuizViewController’s questionLabel outlet will automatically point to the instance of UILabel at the top of the screen. This will allow the BNRQuizViewController to tell this label what question to display.

Set the answerLabel outlet the same way: drag from the circle beside answerLabel to the bottom UILabel (Figure 1.18).

Figure 1.18  Setting answerLabel

Setting answerLabel

Notice that you drag from the object with the outlet that you want to set to the object that you want that outlet to point to.

Your outlets are all set. The next connections you need to make involve the two buttons.

When a UIButton is tapped, it sends a message to another object. The object that receives the message is called the target. The message that is sent is called the action. This action is the name of the method that contains the code to be executed in response to the button being tapped.

In your application, the target for both buttons will be the instance of BNRQuizViewController. Each button will have its own action. Let’s start by defining the two action methods: showQuestion: and showAnwer:

Defining action methods

Return to BNRQuizViewController.m and add the following code in between @implementation and @end.

@implementation

- (IBAction)showQuestion:(id)sender

{

}

- (IBAction)showAnswer:(id)sender

{

}

@end

You will flesh out these methods after you make the target and action connections. The IBAction keyword tells Xcode that you will be making these connections in Interface Builder.

Setting targets and actions

To set an object’s target, 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 select an action.

Let’s start with the Show Question button. You want its target to be BNRQuizViewController and its action to be showQuestion:.

Reopen BNRQuizViewController.xib. Select the Show Question button in the canvas and Control-drag (or right-click and drag) to the File's Owner. When the File's Owner is highlighted, release the mouse button and choose showQuestion: from the pop-up menu, as shown in Figure 1.19.

Figure 1.19  Setting Show Question target/action

Setting Show Question target/action

Now for 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.

Summary of connections

There are now five connections between your BNRQuizViewController and the view objects. You have set the pointers answerLabel and questionLabel to point at the label objects – two connections. The BNRQuizViewController is the target for both buttons – two more. The project’s template made one additional connection: the view pointer of BNRQuizViewController 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. Then in the inspector, click the Summary of connections tab to reveal the connections inspector. (Figure 1.20).

Figure 1.20  Checking connections in the inspector

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. Let’s move on to creating and connecting your model objects.

Creating Model Objects

View objects make up the user interface, so developers typically create, configure, and connect view objects using Interface Builder. Model objects, on the other hand, are set up in code.

In the project navigator, select BNRQuizViewController.m. Add the following code that declares an integer and pointers to two arrays.

@interface BNRQuizViewController ()

@property (nonatomic) int currentQuestionIndex;

@property (nonatomic, copy) NSArray *questions;

@property (nonatomic, copy) NSArray *answers;

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

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

@end

@implementation

@end

The arrays will be ordered lists containing questions and answers. The integer will keep track of what question the user is on.

These arrays need to be ready to go at the same time that the interface appears to the user. To make sure that this happens, you are going to create the arrays right after an instance of BNRQuizViewController is created.

When an instance of BNRQuizViewController is created, it is sent the message initWithNibName:bundle:. In BNRQuizViewController.m, implement the initWithNibName:bundle: method.

...

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

@end

@implementation BNRQuizViewController

- (instancetype)initWithNibName:(NSString *)nibNameOrNil

                         bundle:(NSBundle *)nibBundleOrNil

{

    // Call the init method implemented by the superclass

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if (self) {

        // Create two arrays filled with questions and answers

        // and make the pointers point to them

        self.questions = @[@"From what is cognac made?",

                           @"What is 7+7?",

                           @"What is the capital of Vermont?"];

        self.answers = @[@"Grapes",

                         @"14",

                         @"Montpelier"];

    }

    // Return the address of the new object

    return self;

}

@end

(Scary syntax? Feelings of dismay? Do not panic – you will learn more about the Objective-C language in the next two chapters.)

Using code-completion

As you work through this book, you will type a lot of code. Notice that as you were typing this code, Xcode was ready to fill in parts of it for you. For example, when you started typing initWithNibName:bundle:, it suggested this method before you could finish. You can press the Enter key to accept Xcode’s suggestion or select another suggestion from the pop-up box that appears.

When you accept a code-completion suggestion for a method that takes arguments, Xcode puts placeholders in the areas for the arguments. (Note that this use of the term “placeholder” is completely distinct from the placeholder objects that you saw in the XIB file.)

Placeholders are not valid code, and you have to replace them to build the application. This can be confusing because placeholders often have the same names that you want your arguments to have. So the text of the code looks completely correct, but you get an error.

Figure 1.21 shows two placeholders you might have seen when typing in the previous code.

Figure 1.21  Code-completion placeholders and errors

Code-completion placeholders and errors

See the nibNameOrNil and nibBundleOrNil in the first line of the implementation of initWithNibName:bundle:? Those are placeholders. You can tell because they are inside slightly-shaded, rounded rectangles. The fix is to select the placeholders, type the correct argument name, and press the Enter key. The rounded rectangles will go away, and your code will be correct and valid.

Because the placeholders have the correct text in this case, you can simply select a placeholder and press Enter to have Xcode replace it with an argument of the same name.

When using code-completion, watch out for names that look almost like what you want. Cocoa Touch uses naming conventions which often cause distinct methods, types, and variables to have very similar names. Thus, do not blindly accept the first suggestion Xcode gives you without verifying it. Always double-check.

Pulling it all Together

You have created, configured, and connected your view objects and their view controller. You have created the model objects. Two things are left to do for Quiz:

·        finish implementing the action methods showQuestion: and showAnswer: in BNRQuizViewController

·        add code to BNRAppDelegate that will create and display an instance of BNRQuizViewController

Implementing action methods

In BNRQuizViewController.m, finish the implementations of showQuestion: and showAnswer:.

    ...

    // Return the address of the new object

    return self;

}

- (IBAction)showQuestion:(id)sender

{

    // Step to the next question

    self.currentQuestionIndex++;

    // Am I past the last question?

    if (self.currentQuestionIndex == [self.questions count]) {

        // Go back to the first question

        self.currentQuestionIndex = 0;

    }

    // Get the string at that index in the questions array

    NSString *question = self.questions[self.currentQuestionIndex];

    // Display the string in the question label

    self.questionLabel.text = question;

    // Reset the answer label

    self.answerLabel.text = @"???";

}

- (IBAction)showAnswer:(id)sender

{

    // What is the answer to the current question?

    NSString *answer = self.answers[self.currentQuestionIndex];

    // Display it in the answer label

    self.answerLabel.text = answer;

}

@end

Getting the view controller on the screen

If you were to run Quiz right now, you would not see the interface that you created in BNRQuizViewController.xib. Instead, you would see a blank white screen. To get your interface on screen, you have to connect your view controller with the application’s other controller – BNRAppDelegate.

Whenever you create an iOS application using an Xcode template, an app delegate is created for you. The app delegate is the starting point of an application, and every iOS application has one.

The app delegate manages a single top-level UIWindow for the application. To get the BNRQuizViewController on screen, you need to make it the root view controller of this window.

When an iOS application is launched, it is not immediately ready for the user. There is some setup that goes on behind the scenes. Right before the app is ready for the user, the app delegate receives the message application:didFinishLaunchingWithOptions:. This is your chance to prepare the application for action. In particular, you want to make sure that your interface is ready before the user has a chance to interact with it.

In the project navigator, find and select BNRAppDelegate.m. Add the following code to the application:didFinishLaunchingWithOptions: method to create an instance of BNRQuizViewController and to set it as the root view controller of the app delegate’s window.

#import "BNRAppDelegate.h"

#import "BNRQuizViewController.h"

- (BOOL)application:(UIApplication *)application

        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Override point for customization after application launch

    BNRQuizViewController *quizVC = [[BNRQuizViewController alloc] init];

    self.window.rootViewController = quizVC;

    self.window.backgroundColor = [UIColor whiteColor];

    [self.window makeKeyAndVisible];

    return YES;

}

Now whenever the app is launched, an instance of BNRQuizViewController will be created. This instance will then receive the initWithNibName:bundle: message, which will trigger loading the NIB file compiled from BNRQuizViewController.xib and the creation of the model objects.

Your Quiz is complete. Time to try it out.

Running on the Simulator

First, you are going to run Quiz on Xcode’s iOS simulator. Later, you will see how to run it on an actual device.

To prepare Quiz to run on the simulator, find the current scheme pop-up menu on the Xcode toolbar (Figure 1.22).

Figure 1.22  iPhone Retina (4-inch) scheme selected

iPhone Retina (4-inch) scheme selected

If it says something generic like iPhone Retina (4-inch), then the project is set to run on the simulator and you are good to go. If it says something like Christian's iPhone, then click it and choose iPhone Retina (4-inch) from the pop-up menu.

For this book, use the iPhone Retina (4-inch) scheme. The only difference between that and iPhone Retina (3.5-inch) is the height of the screen. If you select the 3.5-inch simulator, parts of your user interface might get cut off. We will discuss how to scale interfaces for both iPhone screen sizes (and iPad as well) in Chapter 15.

Next, click the iTunes-esque play button in the toolbar. This will build (compile) and then run the application. You will be doing this often enough that you may want to learn and use the keyboard shortcut Command-R.

If building turns up any errors, you can view them in the issue navigator by selecting the iPhone Retina (4-inch) scheme selected tab in the navigator area (Figure 1.23).

Figure 1.23  Issue navigator with example errors and warnings

Issue navigator with example errors and warnings

You can click on any error or warning in the issue navigator to be taken to the file and the line of code where the issue occurred. Find and fix any problems (i.e., code typos!) by comparing your code with the book’s. Then try running the application again. Repeat this process until your application compiles.

Once your application has compiled, it will launch in the iOS simulator. If this is the first time you have used the simulator, it may take a while for Quiz to appear.

Play around with the Quiz application. You should be able to tap the Show Question button and see a new question in the top label; tapping Show Answer should show the right answer. If your application is not working as expected, double-check your connections in BNRQuizViewController.xib.

Deploying an Application

Now that you have written your first iOS application and run it on the simulator, it is time to deploy it to a device.

To install an application on your development device, you need a developer certificate from Apple. Developer certificates are issued to registered iOS Developers who have paid the developer fee. This certificate grants you the ability to sign your code, which allows it to run on a device. Without a valid certificate, devices will not run your application.

Apple’s Developer Program Portal (http://developer.apple.com) contains all the instructions and resources to get a valid certificate. The interface for the set-up process is continually being updated by Apple, so it is fruitless to describe it here in detail. Instead, visit our guide athttp://www.bignerdranch.com/iOS_device_provisioning for instructions.

If you are curious about what exactly is going on here, there are four important items in the provisioning process:

Developer Certificate

This certificate file is added to your Mac’s keychain using Keychain Access. It is used to digitally sign your code.

App ID

The application identifier is a string that uniquely identifies your application on the App Store. Application identifiers typically look like this: com.bignerdranch.AwesomeApp, where the name of the application follows the name of your company. 
The App ID in your provisioning profile must match the bundle identifier of your application. A development profile can have a wildcard character (*) for its App ID and therefore will match any bundle identifier. To see the bundle identifier for the Quiz application, select the project in the project navigator. Then select the Quiz target and the General pane.

Device ID (UDID)

This identifier is unique for each iOS device.

Provisioning Profile

This is a file that lives on your development device and on your computer. It references a Developer Certificate, a single App ID, and a list of the device IDs for the devices that the application can be installed on. This file is suffixed with .mobileprovision.

When an application is deployed to a device, Xcode uses a provisioning profile on your computer to access the appropriate certificate. This certificate is used to sign the application binary. Then, the development device’s UDID is matched to one of the UDIDs contained within the provisioning profile, and the App ID is matched to the bundle identifier. The signed binary is then sent to your development device, where it is confirmed by the same provisioning profile on the device and, finally, launched.

Open Xcode and plug your development device (iPhone, iPod touch, or iPad) into your computer. This should automatically open the Organizer window, which you can re-open at any time using the Window menu’s Organizer item. In the Organizer window, you can select the Devices tab to view all of the provisioning information.

To run the Quiz application on your device, you must tell Xcode to deploy to the device instead of the simulator. Return to the current scheme description in Xcode’s toolbar. Click the description and then choose iOS Device from the pop-up menu (Figure 1.24). If iOS Device is not an option, find the choice that reads something like Christian's iPhone.

Figure 1.24  Choosing the device

Choosing the device

Build and run your application (Command-R), and it will appear on your device.

Application Icons

While running the Quiz application (on your development device or the simulator), return to the device’s Home screen. You will see that its icon is a boring, default tile. Let’s give Quiz a better icon.

An application icon is a simple image that represents the application on the iOS home screen. Different devices require different sized icons, and these requirements are shown in Table 1.1.

Table 1.1  Application icon sizes by device

Device

Application icon sizes

iPhone / iPod touch (iOS 7)

120x120 pixels (@2x)

iPhone / iPod touch (iOS 6 and earlier)

57x57 pixels

114x114 pixels (@2x)

iPad (iOS 7 and earlier)

72x72 pixels

144x144 pixels (@2x)

Every application you deploy to the App Store is required to have icons for every device class on which it can run. For example, if you are supporting just iPhone and iPod touch running iOS 7 or later, then you just need to supply one image (at the resolution listed above). On the other extreme, if you have a universal application which supports iOS 6 and above, you will need to have five different resolution app icons, the two necessary for iPad and the three others necessary for iPhone and iPod touch.

We have prepared an icon image file (size 120x120) for the Quiz application. You can download this icon (along with resources for other chapters) from http://www.bignerdranch.com/solutions/iOSProgramming4ed.zip. Unzip iOSProgramming4ed.zip and find the Icon@2x.png file in the Resourcesdirectory of the unzipped folder.

You are going to add this icon to your application bundle as a resource. In general, there are two kinds of files in an application: code and resources. Code (like BNRQuizViewController.h and BNRQuizViewController.m) is used to create the application itself. Resources are things like images and sounds that are used by the application at runtime. XIB files, which are compiled into NIB files that are read in at runtime, are also resources.

In the project navigator, find Images.xcassets. Select this file to open it and then select AppIcon from the resource list on the left side.

Figure 1.25  Showing the Asset Catalog

Showing the Asset Catalog

This panel is the Asset Catalog where you can manage all of the various images that your application will need.

Drag the Icon@2x.png file from Finder onto the margins of the AppIcon section. This will copy the file into your project’s directory on the filesystem and add a reference to that file in the Asset Catalog. (You can Control-click on a file in the Asset Catalog and select the option to Show in Finder to confirm this.)

Figure 1.26  Adding the App Icon to the Asset Catalog

Adding the App Icon to the Asset Catalog

Build and run the application again. Exit the application and look for the Quiz application with the BNR logo.

(If you do not see the icon, delete the application and then build and run again to redeploy it. On a device, do this as you would any other application. On the simulator, the easiest option is to reset the simulator. With the simulator open, find its menu bar. Select iOS Simulator and then Reset Content and Settings.... This will remove all applications and reset the simulator to its default settings. You should see the app icon the next time you run the application.)

Launch Images

Another resource that you can manage from the Asset Catalog is the application launch image, which appears while an application is loading. The launch image has a specific role on iOS: it conveys to the user that the application is indeed launching and depicts the user interface that the user will interact with once the application has finished launching. Therefore, a good launch image is a content-less screenshot of the application. For example, the Clock application’s launch image shows the four tabs along the bottom, all in the unselected state. Once the application loads, the correct tab is selected and the content becomes visible. (Keep in mind that the launch image is replaced after the application has launched; it does not become the background image of the application.)

In the Resources directory where you found the app icons, there are two launch images: Default@2x.png and Default-568h@2x.png. Open the LaunchImage item in the Asset Catalog, and then drag these images in to the Asset Catalog like you did with the app icons.

Build and run the application. As the application launches, you will briefly see the launch image.

Why two launch images? A launch image must fit the screen of the device it is being launched on. Therefore you need one launch image for 3.5 inch Retina displays, and another launch image for 4 inch Retina displays. Note that if you are supporting iOS6 or earlier on iPhone and iPod touch, you will need to include a third non-Retina launch image. Table 1.2 shows the different size images you will need for each type of device.

Table 1.2  Launch image sizes by device

Device

Launch image size

iPhone/iPod touch without Retina display

320x480 pixels (Portrait only)

iPhone/iPod touch with Retina display (3.5 inch)

640x960 pixels (Portrait only)

iPhone/iPod touch with Retina display (4 inch)

640x1136 pixels (Portrait only)

iPad without Retina display

768x1024 pixels (Portrait)

1024x768 pixels (Landscape)

iPad with Retina display

1536x2048 pixels (Portrait)

2048x1536 pixels (Landscape)

(Note that Table 1.2 lists the screen resolutions of the devices; the real status bar is overlaid on top of the launch image.)

Congratulations! You have written your first application and installed it on your device. Now it is time to dive into the big ideas that make it work.