Chapter 3. Your First iOS App

In this chapter, you’ll build a small Hello World application and run it in iPhone Simulator. If you’re enrolled in the iOS Developer Program, you’ll even get to run the application on your iOS device. I’m going to take you through this step by step, just to give you an idea of how Xcode and Interface Builder work together.

Note

Enrolling in the iOS Developer Program is separate from registering as an iOS developer. Enrollment ($99 or $299 per year, depending on which program you join) provides you with the software certificates and online provisioning tools needed to run your own apps on your own iOS device and submit them for approval to the App Store. See Chapter 2 for more information on registering and enrolling.

I talk in detail about how Objective-C applications are normally structured in Chapter 4. However, in this chapter, although I do get into Objective-C’s sometimes-quirky syntax, I’m going to give you a higher-level overview of the language to get you going quickly.

If you’ve heard someone explain object orientation before, the distinction between the terms class and object may not be totally clear. However, there is a difference. A class is the blueprint for objects; each time you create an object, the class definition determines its structure. An object is a collection of operations (methods) and information (data) that occupies space in memory and can be instructed to perform operations (invoke methods) on that information.

For those of you who are new to programming, the following list defines some of the terms you’ll come across frequently:

Objects and classes
A class consists primarily of two things: variables that can store data and methods that can perform operations. The methods are used to retrieve, set, and manipulate the variables. Objects—sometimes referred to as instances of a class—have specific values associated with these variables. For example, you might use Apple’s UIViewController class to manage the view (i.e., UI) you present to the user of your application. You also might create an instance of that class named myViewController to actually carry out the work of managing the view presented to the user. This would then be referred to as the myViewController object. An instance of a class should not be confused with its implementation, which is the realization of the class in code.
Subclasses
Classes can also inherit functionality from an existing class (the parent or base classes, commonly known as the superclass); classes that inherit functionality in this way are referred to as subclasses. This means you can invoke a method of the parent class on an object that is an instance of a subclass of the parent. Subclassing is normally done so that you can extend the functionality of that class with additional methods or data. For example, when writing applications for iOS devices, you commonly define a subclass of the UIViewController class to manage your views, instead of using the class directly. The subclass of the standard view controller inherits all of the properties of its parent class, but in addition, it allows you to implement code to handle the specific view presented to the user, such as data entry and validation.
Instance and class variables
Both instance and class variables are defined as part of the class declaration. However, every object (instance of the class) holds a separate copy of an instance variable. In other words, if a class defines a variable foo, the value of foo can be different for objects for the same class. Changing the value of an instance variable in one object will not affect the value of the same variable in all the other objects of that class. Conversely, only a single copy of a class variable exists. If you change the value of a class variable from one object, the value of that variable will change for all the objects of that class.
Accessor methods
Accessor methods, sometimes called getters and setters, are usually fairly simple methods used to get and set instance variables in a class. They are used to provide an abstraction layer between variables and the outside world so that the implementation of the class can change without having to change any code outside of the class itself. In Objective-C, the compiler can generate these commonly used functions for you.
Class methods
Class methods (also known as static methods) are similar in nature to class variables. These are methods that are associated directly with the class rather than the object instance; they therefore will not have access to object instance variables.
Events and messages
An event is a message generated by the user interacting with your application’s controls. For instance, if you tap the screen of your iOS device, this generates a UI event in your application that is passed via a message from the application to an object that has been delegated to deal with that specific type of event.
Protocols
A protocol definition declares methods that any class can implement. If your class declares that it abides by a particular protocol definition, you are announcing that you have implemented the minimum mandatory methods declared in the protocol definition, and may optionally have implemented some nonmandatory methods.
Delegate classes
A delegate class is a class that implements a protocol for handling events. Each delegate protocol specifies a number of methods that must be implemented, and additionally methods that may optionally be implemented. Declaring your class a delegate implies that it (at least) implements the mandatory methods. For instance, if your UI has a button, you can declare your class a delegate to handle events generated by the button.
Event loop
The main event loop is the principal control loop for your application. This loop is the process that receives and then passes external events, such as the user tapping the iPhone’s screen or changes in the device’s orientation, to the appropriate delegate classes that you’ve included in your application.
Frameworks and libraries
A framework is a collection of related classes, protocols, and functions collected together within a cohesive architecture. When you make use of a framework, many of the design decisions about how you as a developer will use the code it includes have been taken out of your hands. However, by using the standard frameworks, you inherit standard behavior. For example, when Apple introduced Copy & Paste to the iPhone with the release of version 3.0 of the firmware, it was enabled by default in most third-party applications because the developers made use of the standard UIKit framework to build those applications.

For those of you coming from an object-oriented background, there are a number of differences between the Objective-C model of object orientation and the one implemented by Simula-derived languages such as C++, Java, and C#.

While its nonobject operations are identical to C, Objective-C derives its object syntax almost directly from the Smalltalk language. Its object model is based on sending messages to object instances; in Objective-C you do not invoke a method, but instead send a message. What’s the difference? Invoking a method implies that you know something about that method. Sending a message leaves it up to the receiver of the message to figure out what to do with it.

This kind of loosely coupled chain of command means that Objective-C is much more dynamic at runtime than the Simula-derived languages, but it also means it might appear to be insubordinate.

That’s because in Simula-derived languages, you must know the type of an object before you can call a method on it. In Objective-C, this is not the case. You simply send the object a message. The receiving object then attempts to interpret the message, but there is no guarantee of a response. If it doesn’t understand the message, it will ignore it and return nil. Among other things, this kind of model does away with the need to continually cast objects between types to ensure that you are sending a message that will be understood.

The other main difference is in the way memory is managed. While languages such as Java use garbage collection to handle memory management, in Objective-C memory is managed using reference counting. In the past this was done by hand (see the alloc-retain-release cycle discussion in Chapter 4), but with the introduction of Automatic Reference Counting (ARC) with the arrival of iOS 5, this manual procedure has been much simplified.

While the examples in this book will make use of ARC, it is important to understand what is going on behind the scenes. ARC is a compiler-level feature that simplifies the previous manual management of Objective-C objects; it automatically inserts the appropriate calls into your code at compile time.

Because of this, it is still important to understand manual memory management, especially during the transition from the existing legacy code bases to ARC-native code, as many external libraries will not be compatible with ARC. We’re therefore going to be discussing manual memory management in Chapter 4.

Finally, the applications are almost invariably based on the Model-View-Controller (MVC) design pattern, which is pervasive in the Cocoa Touch and other frameworks that you’ll use to build iOS applications. Rather than encouraging you to create subclasses, the MVC pattern makes use of delegate classes. A pattern is a reusable solution to a commonly occurring problem; in object-oriented programming, patterns usually describe how the developer should model the application in terms of the classes that are used, and how the developer should structure the interactions and relationships between these classes.

For example, the root UIApplication class implements the behavior necessary for an application, but instead of forcing you to subclass the UIApplication class for your own application and add your own code to the subclass, it delivers notification messages of events to an assigned delegate class that implements the UIApplicationDelegate protocol. The UIApplication class asks the delegate class to respond to events when they occur.

I’ll dive a bit deeper into Objective-C as we go through the book, but to make it through this chapter, all you really need to know is that while variable declarations look much the same as variable declarations do in other languages, method calls are surrounded by square brackets. So, for example, both of the following lines of code are method calls:

[anObject someMethod]; 1
[anObject someMethod: anotherObject]; 2
1

The someMethod message is sent to the anObject object.

2

The someMethod message is sent to the anObject object and passes anotherObject as an argument.

Despite the sometimes-quirky syntax (including the square brackets and colon shown in the preceding code) that Objective-C has inherited from Smalltalk, the logic of what is going on should be clear, and we’ll discuss the syntax in much greater detail in the next chapter.

Now let’s create our first application in Xcode. Launch Xcode by double-clicking its icon (it’s located in the /Applications folder on your hard drive). Click “Create a new Xcode project” in the Xcode welcome window.

This will open an Xcode Project window with a drop-down window that will allow you to choose the type of project we’ll be building. We want to build a “Single View Application,” which is one of iOS Application templates supplied by Xcode (see Figure 3-1).

If it’s not already selected, click on the Single View Application template, and then click on the “Next” button. You should then be presented with something that looks a lot like Figure 3-2. In the Product Name box, enter HelloWorld; this will be the name of both the Xcode project and the application target.

Warning

You should make sure you don’t put a space between Hello and World as part of your Project Name, as this can confuse some versions of Xcode.

In the Company Identifier box, enter the root part of your Bundle Identifier [see the section on Creating an App ID in Chapter 2 for more details]. For me, this is uk.co.babilim. You should leave the Class Prefix box blank, and ensure that the Device Family is set to iPhone and the checkbox for ARC is ticked, and the boxes for storyboard and unit tests are not (see Figure 3-2).

Once you’ve filled in the Configuration panel, click on the Next button to proceed. You should then be presented with another dialog to save your new project (see Figure 3-3). You’ll notice that Xcode will create a local Git repository for your project if you want it to. For now at least, let’s ignore that option. Click Create to create and save your first Xcode project.

Xcode will now open a project window, as shown in Figure 3-4. The left pane shows the classes and other files associated with the project, organized into groups in what’s called the Project Navigator. If you click on the arrow next a group icon (represented as yellow folders), the group will expand to show you the files it contains.

The application template you choose determines how the groups are arranged, but you can move the files around and create your own groups if you prefer to organize things differently. The main group at the top of the Project Navigator window is named after your project, and it contains all the classes that make up the application including the .xib files that the Interface Builder application uses to describe your application’s user interface.

The middle pane is the Editor window; by default, the project will open with the Editor window showing the contents of the Project file (the blue document at the top of the Navigator window). This project file contains all the metadata associated with your project. If you click on one of the source code files, which have postfixes .m or .h, you’ll see that the Editor window fills with more familiar source code.

The righthand pane is the Utilities window. Right now, this is empty, but it gives access to Quick Help and other inspectors as well as resources to use in your project. For now, you may want to minimize the utility view by using the Show/Hide button in the Xcode toolbar. See Figure 3-4 above.

When you created the project, Xcode generated a number of files and, along with them, a lot of the boilerplate code you’d otherwise have to laboriously type in. In fact, the project that Xcode generates for you is a complete (if boring) iPhone application. You know those flashlight applications that have proliferated on the App Store? You’ve just written one…

If you click the button in the Xcode toolbar (see Figure 3-4 again), Xcode will compile the application, deploy it into the iPhone Simulator, and then run it. After the application opens, what you see in the simulator should look very similar to Figure 3-5—a simple, blank, gray view.

Let’s look at the files Xcode has generated as part of the template and how it has divided them into separate groups in the Project Navigator view:

The HelloWorld-Prefix.pch prefix header file is implicitly included by each of your source files when they’re built; if you need to include a header file in all of the classes in your project, you can add it here. However, it’s unlikely that you’ll need to do this, so you can safely ignore it for the time being. The HelloWorld-Info.plist (property list) file also plays a role in defining the UI. This property list is an XML file that describes basic information about your application for Xcode and the compiler. The main.m file contains the main() routine; this is the place where your program begins. In this project, the main.m file handles some memory management duties (discussed in Chapter 4) and then calls the UIApplicationMain function, which is the main controller, responsible for handling the event loop. You’ll almost never have to change anything in the Supporting Files group, as the boilerplate code the template generated should serve you fairly well.

Frameworks
The Frameworks group contains a list of external frameworks that your application links to. These frameworks provide the headers and libraries you need to write software for the iPhone OS.
Products
The Products group contains the application binary that is generated when you compile your application. At first the HelloWorld.app file is shown in red. Xcode knows this file should exist, but since you haven’t yet compiled the application, the file currently doesn’t exist.

Note

If you open the Mac OS X Finder and navigate to where you saved the project, you’ll be able to see how the project files are organized on disk. Xcode groups do not necessarily correspond to folders on disk.

Figure 3-6 shows a high-level overview of an iOS application life cycle. This illustrates the main elements of a typical iOS application. Most iOS applications make use of the MVC pattern (see Chapter 4 for more details).

When the user launches your application by tapping its icon on the Home screen, the application’s main() function is called. The main() routine calls the UIApplicationMain function, which is the main application controller responsible for handling the event loop. From this point, the heavy lifting is done by the UIKit framework, which loads the UI and starts the main event loop. During this loop, UIKit dispatches events, such as notification of touches and orientation changes, to your objects and responds to commands issued by your application. When the user performs an action that would cause your application to quit, UIKit notifies your application and begins the termination process.

The application delegate is the core class in your application and receives messages from the main event loop. It is responsible for handling critical system messages. For example, the application delegate handles both the applicationDidFinishLaunching: and the applicationWillTerminate: messages. Every iOS application must contain an application delegate object.

The view controller class is responsible for providing views, or a set of views, and presenting them to the user. The class also acts as a delegate and manages your application’s response to some of the standard system behaviors (e.g., a change in device orientation), rearranging and resizing the views it manages in response to these system events.

Let’s begin at the beginning, with the definition of the application delegate class. Click on the AppDelegate.h file, which contains the declaration of the class:

#import <UIKit/UIKit.h>

@class ViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) ViewController *viewController;

@end

Here we see the app delegate class declaration, also known as the class header file, begins with the @interface directive and ends with the @end directive. This is the delegate class that implements the UIApplicationDelegate protocol and receives messages from the UIApplication class. Breaking down this interface directive, we see that the class is called AppDelegate, it’s a subclass of UIResponder, and it implements the UIApplicationDelegate protocol.

We declare a UIWindow object as part of the class, and after telling the compiler that ViewController is a class using the @class directive further up, we also declare a ViewController object. The UIWindow class defines an object that coordinates the views (the user interface) that we see on the iPhone’s screen. Both of these objects are declared as class properties using the @property name directive. Properties are a generic way of declaring the data that a class provides.

Let’s look at the corresponding implementation. Click on the AppDelegate.m file to open it in the Standard Editor:

#import "AppDelegate.h" 1
#import "ViewController.h"

@implementation AppDelegate 2

- (BOOL)application:(UIApplication *)application
  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window =
        [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 3
    self.viewController = [[ViewController alloc] initWithNibName:
                                         @"ViewController"  bundle:nil]; 4
    self.window.rootViewController = self.viewController; 5
    [self.window makeKeyAndVisible]; 6
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {

}

- (void)applicationDidEnterBackground:(UIApplication *)application {

}

- (void)applicationWillEnterForeground:(UIApplication *)application {

}

- (void)applicationDidBecomeActive:(UIApplication *)application {

}

- (void)applicationWillTerminate:(UIApplication *)application {

}

@end 7
1

The header files are imported with the class declarations for both the AppDelegate and the ViewController classes.

2

This is the beginning of the declaration of the Hello World application delegate class.

3

This statement allocates and initializes the main UIWindow object.

4

Likewise for the ViewController object.

5

Here is the view managed by the viewController object as the root view of the window.

6

This makes the window visible using the makeKeyAndVisible method.

7

This is the end of the declaration of the Hello World application delegate class.

Now let’s examine the implementation’s application:DidFinishLaunchingWithOptions: method. This is where we can insert our own code to customize the application after it launches. See Chapter 5 and the City Guide application for an example of this sort of customization. At the moment, it contains the following:

    self.window = [[UIWindow alloc] initWithFrame:
        [[UIScreen mainScreen] bounds]];
    self.viewController = [[ViewController alloc] initWithNibName:
                                        @"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

You make an object perform an operation by sending a message to the object. Messages are enclosed in square brackets. Inside the brackets, the object receiving the message is on the left side and the message (along with any parameters the message requires) is on the right. The parameters follow the colon [see The Basics of Objective-C Syntax for another example].

Next, let’s look inside the ViewController class. The interface file for this class is called ViewController.h; the implementation file is called ViewController.m.

Let’s start with the interface file. Click on the ViewController.h file in the Classes group to open the file in the Standard Editor.

Back in AppDelegate.h, the application delegate declared a viewController property of the class ViewController (note the capitalization) that right now doesn’t contain any methods or properties of its own:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@end

However, looking at the header file, you’ll see that the ViewController class is a subclass of the UIViewController class. This is the class that provides the fundamental view-management model for iOS applications, and this class is associated in Interface Builder with a nib file (when you create a view-based project, Xcode automatically creates the associated nib file). That nib file contains the UI that will be displayed when we make this view visible.

Next, click on the ViewController.m file in the Classes group and look at the implementation of the class. For now, bear in mind that this subclass relies on its parent class to handle the messages that are left undefined by virtue of being not implemented.

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

@end

I’ve talked about Interface Builder quite a bit so far, but we haven’t looked at it. Let’s do that now. Interface Builder allows you to create and lay out the UI for your iOS application visually; it stores your application’s interface in a bundle (an XML file that, for historic reasons, is generally referred to as a nib file) containing the interface objects and their relationship with your own code. However, unlike almost all other similar design systems that generate code, nib files are serialized (also known as freeze-dried) objects. In other words, the files contain the ready-to-run object instances, rather than code to generate these objects at compile time.

We can use Interface Builder to associate the laid out UI elements with our own code by connecting outlets, actions, and delegates to the UI elements inside the Interface Builder application. However, to do so, we must first declare the objects and methods in our code as either IBOutlets, or IBActions where appropriate, and the classes as delegates.

This IBOutlet or IBAction symbol doesn’t affect how the code is compiled, but it is a place marker to tell Xcode that this object in the code can be connected to a UI component in Interface Builder. This allows the UI constructed in Interface Builder to receive messages from the code. The corresponding IBAction declaration on method declarations, which we’ll meet later, is yet another place marker for Interface Builder, allowing us to connect calling actions in response to events happening in the UI to a method. In many instances, a UI element will also have an associated delegate protocol, and we can declare classes to act as delegates to specific UI elements. Our class will then receive messages when the UI element generates events. For instance, in Chapter 5, you’ll see the UITableView class and associated delegate protocols in action.

Click on the ViewController.xib file. This will open Interface Builder and display the nib file, as shown in Figure 3-7.

When you click on a nib file, the Standard Editor will change to become a visual representation of your user interface. To the left of this, sandwiched between the editing area and the Project Navigator pane, is the dock. The dock shows the Interface Builder objects and placeholders in the nib file (or if using storyboards, the .storyboard file); you can shrink and expand the dock using the button near the bottom of the Editor window (see Figure 3-7).

The Utilities panel to the right provides access to the Inspector tabs, which will allow you to manipulate your objects in the editor, as well as to inspect the connections and other properties of a specific object.

The Constraints button allows us to modify the constraints governing the positioning of user interface items. The left button aligns items, and is the equivalent of choosing Editor→Align. The center button pins items, equivalent of choosing Editor→Pin, while the right button lets you control how constraints are applied when resizing views.

We’ll discuss the details of what’s going on inside Interface Builder in later chapters; for now, we’re just going to add a button and a label to the view. Then we’ll modify our code so that it knows about those elements, and connect those elements to objects in the code. At that point, we’ll have a working Hello World application.

Click on the View icon in the dock, or directly on the view in the Editor panel, to select it, and then pick the Attributes Inspector from the tab bar along the top of the Utilities panel. The Attributes Inspector is the fourth icon along, as shown in Figure 3-8.

Let’s start by changing the rather dull gray background of the view to white. Click on the Background Color box in the View section of the Attributes Inspector to bring up the standard Mac OS X color picker. Push the opacity slider to 100% and change the color to something more interesting. In my case, I picked white, which is only marginally more interesting than gray. Close the color picker; the background of your View window should now be a more interesting color.

Now go to the Object Library (see Figure 3-7) and click and drag a label and a button, Label (UILabel) and Round Rect Button (UIButton), onto your view and drop them in a sensible place.

Delete the placeholder text in the label by double-clicking on the label text to select it and then pressing the Backspace key. This will make the label invisible in the view; however, you can see it’s still there as it’s shown in the dock. If you lose track of where you put it, just click on the Label icon in the dock to select it and it’ll be selected in the view.

You should then add some appropriate replacement text for the button. Just double-click on the button as you did for the label, but this time add some text —“Push me!” perhaps (see Figure 3-9).

In Figure 3-9 you can see some blue vertical lines, these are (some of) the constraints dictating how our user interface will be displayed on different shaped screens.

At this point, we need to tell our code about the user interface elements we added to the view. In the Xcode toolbar, change the Editor type from Standard to Assistant (see Figure 3-10). If you’re short of screen space, for instance, if you’re working on a laptop as I am, you might want to shrink the dock and hide the Utilities panel at the same time to give yourself some extra room to work.

You’ll see that changing from the Standard to the Assistant Editor brings up the interface file that corresponds to the nib file we’re modifying inside Interface Builder (see Figure 3-11).

Now Control-click and drag from the label element you dropped into your view, or from the icon representing the label in the dock, to the header file (between the @interface and @end markers). A pop-up window will appear to create an outlet. Name your outlet “label” and click on the Connect button (see Figure 3-12).

Afterward, Control-click and drag from the button to your code. This time, change the connection type from Outlet to Action before naming your action pushButton. This will not only both define and create a method called pushButton: in your ViewController object, but also connect the button element in Interface Builder to your code. The pushButton: method will be called when the “Touch Up Inside” event (which corresponds to a user tapping on and then releasing the button) is triggered in the interface. We’ll use this to change the text associated with the label and tell the world “Hello!”.

After making these connections, your ViewController.h interface code should look something like this (with the changes highlighted for clarity):

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *label;
- (IBAction)pushButton:(id)sender;

@end

For now, you should just follow along; we’ll discuss the layout of Objective-C methods in the next chapter.

If you click on the ViewController.m file, you’ll see that in addition to adding code to the interface file, Interface Builder has modified our implementation. The changes it made are highlighted:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)pushButton:(id)sender {

}

@end

Interface Builder has automatically synthesized our label property for us, which will in turn automatically generate accessor methods. Additionally, it has added a pushButton: method to the code; this is the hook we’re going to use to change the text of the label.

If you look at the documentation for the UILabel class, you’ll see that all you need to do is to set the text property to change the text displayed by the label:

- (IBAction)pushButton:(id)sender {
    self.label.text = @"Hello World!";
}

Here @"Hello World" is a constant NSString object.

We’re done! Make sure the Scheme in Xcode’s toolbar is set to HelloWorld→iPhone 6.0 Simulator, and click on the Run button. If all goes well, this will start iPhone Simulator and run the code. If there are any issues, the build will fail and you’ll see something like Figure 3-13. Xcode will list the problems in the Navigation panel on the left and automatically jump to the first issue in the Editor window. Here, for instance, I’ve “accidentally typed” self.label.foo rather than self.label.text in the pushButton: method.

However, if all goes well, the application should start in the iPhone Simulator, and you should see something more like Figure 3-14.

Congratulations, you’ve written your first iPhone application. Once you’re done, click on the Stop button in the Xcode toolbar to stop the application running. Now let’s get it to work on your iPhone and iPod touch.