Chapter 3

Handling Basic Interaction

Our Hello, World application was a good introduction to iOS development using Cocoa Touch, but it was missing a crucial capability: the ability to interact with the user. Without that, our application is severely limited in terms of what it can accomplish.

In this chapter, we're going to write a slightly more complex application–sone that will feature two buttons as well as a label, as shown in Figure 3–1. When the user taps either of the buttons, the label's text will change. This may seem like a rather simplistic example, but it demonstrates the key concepts involved in creating interactive iOS apps.

images

Figure 3–1. The simple two-button application we will build in this chapter

The Model-View-Controller Paradigm

Before diving in, a bit of theory is in order. The designers of Cocoa Touch were guided by a concept called Model-View-Controller (MVC), which is a very logical way of dividing the code that makes up a GUI-based application. These days, almost all object-oriented frameworks pay a certain amount of homage to MVC, but few are as true to the MVC model as Cocoa Touch.

The MVC pattern divides all functionality into three distinct categories:

  • Model: The classes that hold your application's data.
  • View: Made up of the windows, controls, and other elements that the user can see and interact with.
  • Controller: The code that binds together the model and view. It contains the application logic that decides how to handle the user's inputs.

The goal in MVC is to make the objects that implement these three types of code as distinct from one another as possible. Any object you create should be readily identifiable as belonging in one of the three categories, with little or no functionality that could be classified as being either of the other two. An object that implements a button, for example, shouldn't contain code to process data when that button is tapped, and an implementation of a bank account shouldn't contain code to draw a table to display its transactions.

MVC helps ensure maximum reusability. A class that implements a generic button can be used in any application. A class that implements a button that does some particular calculation when it is clicked can be used only in the application for which it was originally written.

When you write Cocoa Touch applications, you will primarily create your view components using a visual editor within Xcode called Interface Builder, although you will also modify, and sometimes even create, your user interfaces from code.

Your model will be created by writing Objective-C classes to hold your application's data or by building a data model using something called Core Data, which you'll learn about in Chapter 13. We won't be creating any model objects in this chapter's application, because we do not need to store or preserve data, but we will introduce model objects as our applications get more complex in future chapters.

Your controller component will typically be composed of classes that you create and that are specific to your application. Controllers can be completely custom classes (NSObject subclasses), but more often, they will be subclasses of one of several existing generic controller classes from the UIKit framework, such as UIViewController, which you'll see shortly. By subclassing one of these existing classes, you will get a lot of functionality for free and won't need to spend time recoding the wheel, so to speak.

As we get deeper into Cocoa Touch, you will quickly start to see how the classes of the UIKit framework follow the principles of MVC. If you keep this concept in the back of your mind as you develop, you will end up creating cleaner, more easily maintained code.

Creating Our Project

It's time to create our next Xcode project. We're going to use the same template that we used in the previous chapter: Single View Application. By starting with this simple template again, it will be easier for you to see how the view and controller objects work together in an iOS application. We'll use some of the other templates in later chapters.

Launch Xcode and select File images New images New Project… or press imagesimagesN. Select the Single View Application template, and then click Next.

You'll be presented with the same options sheet as you saw in the previous chapter. In the Product Name field, type the name of our new application, Button Fun. The Company Identifier field should still have the value you used in the previous chapter, so you can leave that alone. In the Class Prefix field, use the same value as you did in the previous chapter: BID.

Just as we did with Hello, World, we're going to write an iPhone application, so select iPhone for Device Family. We're not going to use storyboards or unit tests, so you can leave both of those options unchecked. However, we do want to use ARC, so check the Use Automatic Reference Counting box. We'll explain ARC later in the chapter. Figure 3–2 shows the completed options sheet.

images

Figure 3–2. Naming your project and selecting options

Hit Next, and you'll be prompted for a location for your project. You can leave the Create local git repository checkbox unchecked. Save the project with the rest of your book projects.

Looking at the View Controller

A little later in this chapter, we'll design a view (or user interface) for our application using Interface Builder, just as we did in the previous chapter. Before we do that, we're going to look at and make some changes to the source code files that were created for us. Yes, Virginia, we're actually going to write some code in this chapter.

Before we make any changes, let's look at the files that were created for us. In the project navigator, the Button Fun group should already be expanded, but if it's not, click the disclosure triangle next to it (see Figure 3–3).

images

Figure 3–3. The project navigator showing the class files that were created for us by the project template. Note that our class prefix was automatically incorporated into the class file names.

The Button Fun folder should contain four source code files (the ones that end in .h or .m) and a single nib file. These four source code files implement two classes that our application needs: our application delegate and the view controller for our application's only view. Notice that Xcode automatically added the prefix we specified to all of our class names.

We'll look at the application delegate a little later in the chapter. First, we'll work with the view controller class that was created for us.

The controller class called BIDViewController is responsible for managing our application's view. The BID part of the name is derived automatically from the class prefix we specified, and the ViewController part of the name identifies that this class is, well, a view controller. Click BIDViewController.h in the Groups & Files pane, and take a look at the contents of the class's header file:

#import <UIKit/UIKit.h>

@interface BIDViewController : UIViewController

@end

Not much to it, is there? BIDViewController is a subclass of UIViewController, which is one of those generic controller classes we mentioned earlier. It is part of the UIKit and, by subclassing it, we get a bunch of functionality for free. Xcode doesn't know what our application-specific functionality is going to be, but it does know that we're going to have some, so it has created this class for us to write that application-specific functionality.

Understanding Outlets and Actions

In Chapter 2, you used Xcode's Interface Builder to design a user interface. A moment ago, you saw the shell of a view controller class. There must be some way for the code in this view controller class to interact with the objects in the nib file, right?

Absolutely! A controller class can refer to objects in a nib file by using a special kind of property called an outlet. Think of an outlet as a pointer that points to an object within the nib. For example, suppose you created a text label in Interface Builder (as we did in Chapter 2) and wanted to change the label's text from within your code. By declaring an outlet and connecting that outlet to the label object, you would then be able to use the outlet from within your code to change the text displayed by the label. You'll see how to do just that in this chapter.

Going in the opposite direction, interface objects in our nib file can be set up to trigger special methods in our controller class. These special methods are known as action methods (or just actions). For example, you can tell Interface Builder that when the user taps a button, a specific action method within your code should be called. You could even tell Interface Builder that when the user first touches a button, it should call one action method, and then later when the finger is lifted off the button, it should call a different action method.

Prior to Xcode 4, we would have needed to create our outlets and actions here in the view controller's header file before we could go to Interface Builder and start connecting outlets and actions. Xcode 4's assistant view gives us a much faster and more intuitive approach that lets us create and connect outlets and actions simultaneously, a process we're going to look at shortly. But before we start making connections, let's talk about outlets and actions in a little more detail. Outlets and actions are two of the most basic building blocks you'll use to create iOS apps, so it's important that you understand what they are and how they work.

Outlets

Outlets are special Objective-C class properties that are declared using the keyword IBOutlet. Declaring an outlet is done in your controller class header file, and might look something like this:

@property (nonatomic, retain) IBOutlet UIButton *myButton;

This example is an outlet called myButton, which can be set to point to any button in Interface Builder.

The IBOutlet keyword is defined like this:

#ifndef IBOutlet
#define IBOutlet
#endif

Confused? IBOutlet does absolutely nothing as far as the compiler is concerned. Its sole purpose is to act as a hint to tell Xcode that this is a property that we're going to want to connect to an object in a nib file. Any property that you create and want to connect to an object in a nib file must be preceded by the IBOutlet keyword. Fortunately, Xcode will now create outlets for us automatically.

Actions

In a nutshell, actions are methods that are declared with a special return type, IBAction, which tells Interface Builder that this method can be triggered by a control in a nib file. The declaration for an action method will usually look like this:

- (IBAction)doSomething:(id)sender;

or like this:

- (IBAction)doSomething;

The actual name of the method can be anything you want, but it must have a return type of IBAction, which is the same as declaring a return type of void. A void return type is how you specify that a method does not return a value. Also, the method must either take no arguments or take a single argument, usually called sender. When the action method is called, sender will contain a pointer to the object that called it. For example, if this action method was triggered when the user taps a button, sender would point to the button that was tapped. The sender argument exists so that you can respond to multiple controls using a single action method. It gives you a way to identify which control called the action method.

TIP There's actually a third, lesser-used type of IBAction declaration that looks like this:

- (IBAction)doSomething:(id)sender
               forEvent:(UIEvent *)event;

We'll talk about control events starting in the next chapter.

It won't hurt anything if you declare an action method with a sender argument and then ignore it. You will likely see a lot of code that does just that. Action methods in Cocoa and NeXTSTEP needed to accept sender whether they used it or not, so a lot of iOS code, especially early iOS code, was written that way.

Now that you understand what actions and outlets are, you'll see how they work as we design our user interface. Before we start doing that, however, we have one quick piece of housekeeping to do to keep everything neat and orderly.

Cleaning Up the View Controller

Single-click BIDViewController.m in the project navigator to open the implementation file. As you can see, there's a fair bit of boilerplate code that was provided for us by the project template we chose. These methods are ones that are commonly used in UIViewController subclasses, so Xcode gave us stub implementations of them, and we can just add our code there. However, we don't need most of these stub implementations for this project, so all they're doing is taking up space and making our code harder to read. We're going to do our future selves a favor and delete what we don't need.

Delete all the methods except for viewDidUnload. When you're finished, your implementation should look like this:

#import "BIDViewController.h"
@implementation BIDViewController

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

@end

That's much simpler, huh? Don't worry about all those methods you just deleted. You'll be introduced to most of them throughout the course of the book.

The method we've left in is one that every view controller with outlets should implement. When a view is unloaded, which can happen when the system needs to make additional memory available, it's important to nil out your outlets. If you don't, the memory used by those outlets will not be released. Fortunately, all we need to do is leave this empty implementation in place, and Xcode will take care of releasing any outlets we create, as you'll see in this chapter.

Designing the User Interface

Make sure you save the changes you just made, and then single-click BIDViewController.xib to open your application's view in Xcode's Interface Builder (see Figure 3–4). As you'll remember from the previous chapter, the gray window that shows up in the editor represents your application's one and only view. If you look back at Figure 3–1, you can see that we need to add two buttons and a label to this view.

Let's take a second to think about our application. We're going to add two buttons and a label to our user interface, and that process is very similar to what we did in the previous chapter. However, we're also going to need outlets and actions to make our application interactive.

The buttons will need to each trigger an action method on our controller. We could choose to make each button call a different action method, but since they're going to do essentially the same task (update the label's text), we will need to call the same action method. We'll differentiate between the two buttons using that sender argument we discussed earlier in the section on actions. In addition to the action method, we'll also need an outlet connected to the label so that we can change the text that the label displays.

images

Figure 3–4. BIDViewController.xib open for editing in Xcode's Interface Builder

Let's add the buttons first, and then place the label. We'll create the corresponding actions and outlets as we design our interface. We could also manually declare our actions and outlets, and then connect our user interface items to them, but why do extra work when Xcode will do it for us?

Adding the Buttons and Action Method

Our first order of business is to add two buttons to our user interface. We'll then have Xcode create an empty action method for us and connect both buttons to that action method. This will cause the buttons, when tapped by the user, to call that action method. Any code we place in that action method will be executed when the user taps the button.

Select View images Utilities images Show Object Library or press ^ imagesimages3 to open the object library. Type UIButton into the object library's search box (you actually need to type only the first four characters, UIBu, to narrow down the list). Once you're finished typing, only one item should appear in the object library: Round Rect Button (see Figure 3–5).

images

Figure 3–5. The Round Rect Button as it appears in the object library

Drag Round Rect Button from the library and drop it on the gray view. This will add a button to your application's view. Place the button along the left side of the view, using the blue guidelines that appear to place it the appropriate distance from the left edge. For vertical placement, use the blue guideline to place the button halfway down in the view. You can use Figure 3–1 as a placement guide, if that helps.

NOTE: The little, blue guidelines that appear as you move objects around in Interface Builder are there to help you stick to the iOS Human Interface Guidelines (usually referred to as “the HIG”). Apple provides the HIG for people designing iPhone and iPad applications. The HIG tells you how you should—and shouldn't—design your user interface. You really should read it, because it contains valuable information that every iOS developer needs to know. You'll find it at http://developer.apple.com/iphone/library/documentation/UserExperience/Conceptual/MobileHIG/.

Double-click the newly added button. This will allow you to edit the button's title. Give this button a title of Left.

Now, it's time for some Xcode 4 magic. Select View images Assistant Editor images Show Assistant Editor or press imagesimagesimages to open the assistant editor. You can also show and hide the assistant editor by clicking the middle editor button in the collection of seven buttons on the upper-right side of the project window (see Figure 3–6).

images

Figure 3–6. The Show the Assistant editor toggle button

Unless you specifically request otherwise (see the options in the Assistant Editor menu), the assistant editor will appear to the right of the editing pane. The left side will continue to show Interface Builder, but the right will display BIDViewController.h, which is the header file for the view controller that “owns” this nib.

TIP: After opening the assistant editor, you may need to resize your window to have enough room to work. If you're on a smaller screen, like the one on a MacBook Air, you might need to close the utility view and/or project navigator to give yourself enough room to use the assistant editor effectively. You can do this easily using the three view buttons in the upper-right side of the project window (see Figure 3–6).

Remember the File's Owner icon we discussed in the previous chapter? The object that loads a nib is considered its owner, and with the case of nibs like this one that define the user interface for one of an application's views, the owner of the nib is the corresponding view controller class. Because our view controller class is the file's owner, the assistant editor knows to show us the header of the view controller class, which is the most likely place for us to connect actions and outlets.

As you saw earlier, there's really not much in BIDViewController.h. It's just an empty UIViewController subclass. But it won't be an empty subclass for long!

We're now going to ask Xcode to automatically create a new action method for us and associate that action with the button we just created.

To do this, begin by clicking your new button so it is selected. Now, hold down the control key on your keyboard, and then click and drag from the button over to the source code in the assistant editor. You should see a blue line running from the button to your cursor (see Figure 3–7). This blue line is how we connect objects in nibs to code or other objects.

Tip. You can drag that blue line to anything you want to connect to your button: to the header file in the assistant editor, to the File's Owner icon, to any of the other icons on the left side of the editing pane, or even to other objects in the nib.

images

Figure 3–7. Control-dragging to source code will give you the option to create an outlet, action, or outlet collection.

If you move your cursor so it's between the @interface and @end keywords (as shown in Figure 3–7), a gray box will appear, letting you know that releasing the mouse button will insert an outlet, an action, or an outlet collection for you.

NOTE: We make use of actions and outlets in this book, but we do not use outlet collections. Outlet collections allow you to connect multiple objects of the same kind to a single NSArray property, rather than creating a separate property for each object.

To finish this connection, release your mouse button, and a floating popup will appear, like the one shown in Figure 3–8. This window lets you customize your new action. In the window, click the popup menu labeled Connection, and change the selection from Outlet to Action. This tells Xcode that we want to create an action instead of an outlet.

images

Figure 3–8. The floating popup that appears after you control-drag to source code

The popup will change to look like Figure 3–9. In the Name field, type buttonPressed. When you're finished, do not hit return. Pressing return would finalize our outlet, and we're not quite ready to do that. Instead, press tab to move to the Type field and type in UIButton, replacing the default value of id.

NOTE: As you probably remember, an id is a generic pointer that can point to any Objective-C object. We could leave this as id, and it would work fine, but if we change it to the class we expect to call the method, the compiler can warn us if we try to do this from the wrong type of object. There are times when you'll want the flexibility to be able to call the same action method from different types of controls, and in those cases, you would want to leave this set to id. In our case, we're only going to call this method from buttons, so we're letting the Xcode and LLVM know that. Now, it can warn us if we unintentionally try to connect something else to it.

images

Figure 3–9. Changing the connection type to Action changes the appearance of the popup.

There are two fields below Type, which we will leave at their default values. The Event field lets you specify when the method is called. The default value of Touch Up Inside fires when the user lifts a finger off the screen if, and only if, the finger is still on the button. This is the standard event to use for buttons. This gives the user a chance to reconsider. If the user moves a finger off the button before lifting it off the screen, the method won't fire.

The Arguments field lets you choose between the three different method signatures that can be used for action methods. We want the sender argument so that we can tell which button called the method. That's the default, so we just leave it as is.

Hit the return key or click the Connect button, and Xcode will insert the action method for you. Your BIDViewController.h file should now look like this:

#import <UIKit/UIKit.h>

@interface BIDViewController : UIViewController
- (IBAction)buttonPressed:(id)sender;

@end

NOTE: Over time, Apple will tweak both Xcode and the code templates we've been using. When that happens, you may need to make some adjustments to our step-by-step instructions. In the current example, we would expect to see UIButton instead of id in the declaration of the buttonPressed parameter. Likely, this will eventually be tweaked, and you'll need to make a change or two to this approach. But this is no big deal; that's the nature of the beast.

Xcode has now added a method declaration to your class's header file for you. Single-click BIDViewController.m to look at the implementation file, and you'll see that it has also added a method stub for you.

- (IBAction)buttonPressed:(id)sender {
}

In a few moments, we'll come back here to write the code that needs to run when the user taps either button. In addition to creating the method declaration and implementation, Xcode has also connected that button to this action method and stored that information in the nib file. That means we don't need to do anything else to make that button call this method when our application runs.

Go back to BIDViewController.xib and drag out another button, this time placing the button on the right side of the screen. After placing it, double-click it and change its name to Right. The blue lines will pop up to help you align it with the right margin, as you saw before, and they will also help you align the button vertically with the other button.

TIP: Instead of dragging a new object out from the library, you could hold down the option key and drag the original object (the Left button in this example) over. Holding down the option key tells Interface Builder to make a copy of the object you drag.

This time, we don't want to create a new action method. Instead, we want to connect this button to the existing one that Xcode created for us a moment ago. How do we do that? We do it pretty much the same way as we did for the first button.

After changing the name of the button, control-click the new button and drag toward your header file again. This time, as your cursor gets near the declaration of buttonPressed:, that method should highlight, and you'll get a gray popup saying Connect Action (see Figure 3–10). When you see that popup, release the mouse button. and Xcode will connect this button to the existing action method. That will cause this button, when tapped, to trigger the same action method as the other button.

images

Figure 3–10. Dragging to an existing action to whitespace will connect the button to an existing action.

Note that this will work even if you control-drag to connect your button to a method in your implementation file. In other words, you can control-drag from your new button to the buttonPressed declaration in BIDViewController.h or to the buttonPressed method implementation in BIDViewController.m. Xcode 4 sure am smart!

Adding the Label and Outlet

In the object library, type Label into the search field to find the Label user interface item (see Figure 3–11). Drag the Label to your user interface, somewhere above the two buttons you placed earlier. After placing it, use the resize handles the stretch the label from the left margin to the right margin. That should give it plenty of room for the text we'll be displaying to the user.

images

Figure 3–11. The label as it appears in the object library

Labels, by default, are left-justified, but we want this one to be centered. Select View images Utilities images Show Attributes Inspector (or press imagesimages4) to bring up the attributes inspector (see Figure 3–12). Make sure the label is selected, and then look in the attributes inspector for the Alignment buttons. Select the middle Alignment button to center the label's text.

images

Figure 3–12. The attribute inspector for the label

Before the user taps a button, we don't want the label to say anything, so double-click the label (so the text is selected) and press the delete button on your keyboard. That will delete the text currently assigned to the label. Hit return to commit your changes. Even though you won't be able to see the label when it's not selected, don't worry—it's still there.

TIP: If you have invisible user interface elements, like empty labels, and want to be able to see where they are, select Canvas from the Assistant Editor menu, and then from the submenu that pops up, turn on Show Bounds Rectangles.

All that's left is to create an outlet for the label. We do this exactly the way we created and connected actions earlier. Make sure the assistant editor is open and displaying BIDViewController.h. If you need to switch files, use the popup above the assistant editor.

Next, select the label in Interface Builder and control-drag from the label to the header file. Drag until your cursor is right above the existing action method. When you see something like Figure 3–13, let go of the mouse button, and you'll see the popup window again (shown earlier in Figure 3–8).

images

Figure 3–13. Control-dragging to create an outlet

We want to create an outlet, so leave the Connection at the default type of Outlet. We want to choose a descriptive name for this outlet so we'll remember what it is used for when we're working on our code. Type statusText into the Name field. Leave the Type field set to UILabel. The final field, labeled Storage, can be left at the default value.

Hit return to commit your changes, and Xcode will insert the outlet property into your code. Your controller class's header file should now look like this:

#import <UIKit/UIKit.h>

@interface BIDViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *statusText;
- (IBAction)buttonPressed:(id)sender;
@end

Now, we have an outlet, and Xcode has automagically connected the label to our outlet. This means that if we make any changes to statusText in code, those changes will affect the label on our user interface. If we set the text property on statusText, for example, it will change what text is displayed to the user.

Single-click BIDViewController.m in the project navigator to look at the implementation of our controller. There, you'll see that Xcode has inserted a @synthesize statement for us for the property that it created. It also did something else. Remember that method that we left in our code when we deleted the boilerplate methods? Look at it now:

- (void)viewDidUnload {
    [self setStatusText:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

See that line of code above the call to super? Xcode added that automatically as well. When our view is unloaded, we need to “let go” of all of our outlets; otherwise, their memory can't be freed. Assigning a value of nil to the outlet does just that—it allows the previous value to be released from memory.

Essentially, control-dragging to create the outlet did everything we needed to set up the outlet for use.

Writing the Action Method

So far, we've designed our user interface, and wired up both outlets and actions to our user interface. All that's left to do is to use those actions and outlets to set the text of the label when a button is pressed. You should still be in BIDViewController.m, but if you're not, single-click that file in the project navigator to open it in the editor. Find the empty buttonPressed: method that Xcode created for us earlier.

In order to differentiate between the two buttons, we're going to use the sender parameter. We'll retrieve the title of the button that was pressed using sender, and then create a new string based on that title, and assign that as the label's text. Add the bold code below to your empty method:

- (IBAction)buttonPressed:(UIButton *)sender {
    NSString *title = [sender titleForState:UIControlStateNormal];
    statusText.text = [NSString stringWithFormat:@"%@ button pressed.", title];
}

This is pretty straightforward. The first line retrieves the tapped button's title using sender. Since buttons can have different titles depending on their current state, we use the UIControlStateNormal parameter to specify that we want the title when the button is in its normal, untapped state. This is usually the state you want to specify when asking a control (a button is a type of control) for its title. We'll look at control states in more detail in Chapter 4.

The next line creates a new string by appending the text “button pressed.” to the title we retrieved in the previous line. So, if the left button, which has a title of Left, is tapped, this line will create a string that says “Left button pressed.” This new string is assigned to the label's text property, which is how we change the text that the label is displaying.

Trying It Out

Guess what? We're basically finished. Are you ready to try out our app? Let's do it!

Select Product images Run. If you run into any compile or link errors, go back and compare your code changes to those shown in this chapter. Once your code builds properly, Xcode will launch the iPhone simulator and run your application. When you tap the right button, the text “Right button pressed.” should appear (as in Figure 3–1). If you then tap the left button, the label will change to say “Left button pressed.”

Looking at the Application Delegate

Well, cool, your application works! Before we move on to our next topic, let's take a minute to look through the two source code files we have not yet examined, BIDAppDelegate.h and BIDAppDelegate.m. These files implement our application delegate.

Cocoa Touch makes extensive use of delegates, which are classes that take responsibility for doing certain tasks on behalf of another object. The application delegate lets us do things at certain predefined times on behalf of the UIApplication class. Every iOS application has one and only one instance of UIApplication, which is responsible for the application's run loop and handles application-level functionality such as routing input to the appropriate controller class. UIApplication is a standard part of the UIKit, and it does its job mostly behind the scenes, so you generally don't need to worry about it.

At certain well-defined times during an application's execution, UIApplication will call specific methods on its delegate, if there is a delegate and that delegate implements the method. For example, if you have code that needs to fire just before your program quits, you would implement the method applicationWillTerminate: in your application delegate and put your termination code there. This type of delegation allows your application to implement common application-wide behavior without needing to subclass UIApplication or, indeed, without needing to know anything about the inner workings of UIApplication.

Click BIDAppDelegate.h in the project navigator to see the application delegate's header file. It should look similar to this:

#import <UIKit/UIKit.h>

@class BIDViewController;

@interface BIDAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) BIDViewController *viewController;

@end

One thing worth pointing out is this line of code:

@interface BIDAppDelegate : UIResponder <UIApplicationDelegate>

Do you see that value between the angle brackets? This indicates that this class conforms to a protocol called UIApplicationDelegate. Hold down the option key. Your cursor should turn into crosshairs. Move your cursor so that it is over the word UIApplicationDelegate. Your cursor should turn into a pointing hand with a question mark in the center, and the word UIApplicationDelegate should be highlighted, as if it were a link in a browser (see Figure 3–14).

images

Figure 3–14. When you hold down the option key in Xcode and point at a symbol in your code, the symbol is highlighted and your cursor changes into a pointing hand with a question mark.

With the option key still held down, click this link. This will open a small popup window showing a brief overview of the UIApplicationDelegate protocol, as shown in Figure 3–15.

images

Figure 3–15. When we option-clicked <UIApplicationDelegate> from within our source code, Xcode popped up this window, called the Quick Help panel, which describes the protocol.

Notice the two icons in the upper-right corner of this new popup documentation window (see Figure 3–15). Click the left icon to view the full documentation for this symbol, or click the right icon to view the symbol's definition in a header file. This same trick works with class, protocol, and category names, as well as method names displayed in the editor pane. Just option-click a word, and Xcode will search for that word in the documentation browser.

Knowing how to quickly look up things in the documentation is definitely worthwhile, but looking at the definition of this protocol is perhaps more important. Here's where you'll find which methods the application delegate can implement and when those methods will be called. It's probably worth your time to read over the descriptions of these methods.

NOTE: If you've worked with Objective-C before but not with Objective-C 2.0, you should be aware that protocols can now specify optional methods. UIApplicationDelegate contains many optional methods. However, you do not need to implement any of the optional methods in your application delegate unless you have a reason to do so.

Back in the project navigator, click BIDAppDelegate.m to see the implementation of the application delegate. It should look something like this:

#import "BIDAppDelegate.h"

#import "BIDViewController.h"

@implementation BIDAppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[BIDViewController alloc] initWithNibName:@"BIDViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
  /*
   Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
   Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
   */
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
  /*
   Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
   If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
   */
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
  /*
   Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
   */
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
  /*
   Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
   */
}

- (void)applicationWillTerminate:(UIApplication *)application
{
  /*
   Called when the application is about to terminate.
   Save data if appropriate.
   See also applicationDidEnterBackground:.
   */
}
@end

At the top of the file, you can see that our application delegate has implemented one of those protocol methods covered in the documentation, called application:didFinishLaunchingWithOptions:. As you can probably guess, this method fires as soon as the application has finished all the setup work and is ready to start interacting with the user.

Our delegate version of application:didFinishLaunchingWithOptions: creates a window, and then it creates an instance of our controller class by loading the nib file that contains our view. It then adds that controller's view as a subview to the application's window, which makes the view visible. This is how the view we designed is shown to the user. You don't need to do anything to make this happen; it's all part of the code generated by the template we used to build this project, but it's good to know that it happens here.

We just wanted to give you a bit of background on application delegates and show how this all ties together before closing this chapter.

Bring It on Home

This chapter's simple application introduced you to MVC, creating and connecting outlets and actions, implementing view controllers, and using application delegates. You learned how to trigger action methods when a button is tapped and saw how to change the text of a label at runtime. Although we built a simple application, the basic concepts we used are the same as those that underlie the use of all controls under iOS, not just buttons. In fact, the way we used buttons and labels in this chapter is pretty much the way that we will implement and interact with most of the standard controls under iOS.

It's critical that you understand everything we did in this chapter and why we did it. If you don't, go back and redo the parts that you don't fully understand. This is important stuff! If you don't make sure you understand everything now, you will only get more confused as we get into creating more complex interfaces later in this book.

In the next chapter, we'll take a look at some of the other standard iOS controls. You'll also learn how to use alerts to notify the user of important happenings and how to use action sheets to indicate that the user needs to make a choice before proceeding. When you feel you're ready to proceed, give yourself a pat on the back for being such an awesome student, and head on over to the next chapter.

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

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