Chapter 6
UIApplication and UIApplicationDelegate

Key Skills & Concepts

• Understanding the UIApplication class

• Understanding the UIApplicationDelegate protocol

• Handling application startup and termination

• Handling application interruptions

Every iOS application has one UIApplication. UIApplication is an iOS application’s starting point and is responsible for initializing and displaying your application’s UIWindow. It is also responsible for loading your application’s first UIView into the UIWindow. Another responsibility UIApplication has is managing your application’s life cycle. UIApplication fulfills this management responsibility using a delegate called UIApplicationDelegate. Although UIApplication receives events, it’s the UIApplicationDelegate that handles how an application responds to those events. Events the UIApplicationDelegate might handle include application life cycle events, such as startup and shutdown, and system events like incoming phone calls and calendar alerts. In this chapter, after learning how to load an application’s root view into the UIWindow, you explore handling system events using the UIApplicationDelegate protocol.

Try This: Adding a UIView and UIViewController to a UIApplicationDelegate

Before continuing, create this chapter’s project; this chapter uses the same project throughout. In this project, you start with the simplest iOS template, a Window-based application. You’ll create the application from scratch by first creating a xib and a corresponding view controller. You’ll then modify the application’s delegate so that it loads the view.

1. Create a new Window-based Application in Xcode by selecting File | New | New Project and then selecting Application under iOS in the left column and Window-Based Application. Select iPhone in the Device Family pull-down. Name the project AddViewProject.

2. In the navigation pane, expand the Classes folder. This folder contains the AddViewProject AppDelegate.h and AddViewProjectAppDelegate.m files. These two files implement the project’s custom class that adopts the UIApplicationDelegate protocol.

Image

Figure 6-1 Creating an Empty XIB Interface Builder

3. Highlight the Resources folder. CTRL-click and select New File from the pop-up menu. Select User Interfaces from the New File dialog, and select Empty XIB (Figure 6-1). You may also have to select Resources as the group in the pull-down when naming the file.

4. Name the xib FirstViewController and click Finish.

5. Highlight the Classes folder. Select File | New File from the menu.

6. Select the UIViewController subclass from the Cocoa Touch Classes and click Next (Figure 6-2).

NOTE
You could have created the view controller first and then checked the “With XIB for user interface” check box; Xcode would then have generated the xib for you.

Image

Figure 6-2 Creating a UIViewController

7. Name the file FirstViewController.m. Click Finish.

8. Click FirstViewController.xib to open it in Interface Builder. Select View | Utilities | Object Library from the main menu to display the object library in the lower-right Libraries pane.

9. Scroll down to the View object, and drag and drop it onto the FirstViewController.xib Document window.

10. Select File’s Owner icon (the transparent cube to the left of the drawing area). Select View | Utilities | Identity from the main menu to switch the Inspector pane to display object identity. Now select FirstViewController as the class in the pull-down menu (Figure 6-3).

Image

Figure 6-3 Select FirstViewController as the file’s owner.

11. Select the File Owner icon again. Select View | Utilities | Connections from the main menu (or just click the connections button at the top of the Utilities Area). Drag from the circle next to View to the view in the drawing area to set the newly created view as FirstViewController’s view outlet (Figure 6-4).

12. Select the view, select View | Utilities | Object Attributes from the main menu and then click in the background color box to change its color (Figure 6-5).

13. Save FirstViewController.xib.

14. Open AddViewProjectAppDelegate.h, import FirstViewController.h, and create a property referencing the FirstViewController class (Listing 6-1).

Image

Figure 6-4 Setting the view as the File’s Owner view

Listing 6-1 AddViewProjectAppDelegate.h interface

#import <UIKit/UIKit.h>
#import "FirstViewController.h"
@interface AddViewProjectAppDelegate : NSObject
<UIApplicationDelegate> {
  UIWindow *window;
  FirstViewController *first;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) FirstViewController *first;
@end

Image

Figure 6-5 Changing the view’s color

15. Open AddViewProjectAppDelegate.m, synthesize first, and modify applicationDidFinish Launching: so that it obtains a reference to FirstViewController from FirstViewController.xib and then adds its view as a subview to the window. FirstViewController.m should appear identical to Listing 6-2. Don’t forget to deallocate the view in the delegate’s dealloc method.

Listing 6-2 AddViewProjectAppDelegate.m implementation

#import "AddViewProjectAppDelegate.h"
@implementation AddViewProjectAppDelegate
@synthesize window;
@synthesize first;

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

  first = [[FirstViewController alloc]
      initWithNibName:@"FirstViewController" bundle:nil];
  [window addSubview: [first view]];
  [window makeKeyAndVisible];
  return YES;
}

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

    // Save data if appropriate.
}
 -(void)dealloc {
  [window release];
  [first release];
  [super dealloc];
}
@end

16. Click the Run button. Your colored view should load into the iPhone Simulator (Figure 6-6).

Image

Figure 6-6 The application in iPhone Simulator

In Steps 10 and 11, you manually connected AddViewProjectAppDelegate to its UIView. Moreover, you placed that view in its own nib. Every nib has an owner. Recall that every application has one UIWindow. UIWindow is in a project’s MainWindow.xib. That nib’s owner is UIApplication. Also notice that Xcode added the AddViewProjectAppDelegate to MainWindow.xib and connected it to the UIWindow and set the UIApplication’s delegate.

Nibs you create should have a class adopting the UIViewController protocol as an owner, which is what you did in Step 10. In Step 9, you tied the UIView created in the nib in Interface Builder to the UIViewController created in Xcode. This is how the two objects “know” about each other. You learn more about UIViewControllers and UIViews—and connecting them—in Chapter 7.

NOTE
Notice that you created FirstViewController’s view in its own FirstViewController.xib file. You could have opened MainWindow.xib, dragged a view onto the window, and used this nib for your user interface. But this is not the preferred way of using views in nibs. Apple recommends one view per nib file. The reason for this recommendation is that an application must load all views and all controls that reside in the same nib. Using a new nib file for each view reduces your application’s memory use because you only load views as needed.

Connecting UIWindow, UIApplication, and UIApplicationDelegate

In the preceding section, I only briefly mentioned the connections in MainWindow.xib. But these connections warrant a closer look if you want to understand what the template actually did. Notice the UIWindow in Listing 6-1 is an IBOutlet. Your first experience with IBOutlets was in Chapter 1; you learn more on it in Chapter 7. But realize the window “lives” in the xib, not in the delegate. Although the window is released by the delegate in the dealloc method, it is neither allocated nor initialized by the delegate’s code in Listing 6-2. Remember, all the dealloc method in Listing 6-2 is doing is releasing the class’s reference to the window, not deallocating the window. Instead, MainWindow.xib handles allocating, initializing, and deallocating the UIWindow.

UIApplication knows to load MainWindow.xib by consulting the NSMainNibFile key in the Info.plist file. If you open the AddViewProject project’s Info.plist, you will see that the “Main nib file base name” is set to MainWindow. While loading, the nib sets AddViewProjectApp Delegate as UIApplication’s delegate and UIWindow as AddViewProjectAppDelegate’s window. Both are outlets of their respective class in Interface Builder.

Try This: Exploring Main Window.xib

1. Open MainWindow.xib and display the document window.

2. Highlight the File’s Owner and select the Object Identity tab in the Inspector. Notice its Custom Class is set to UIApplication (Figure 6-7). UIApplication loads MainWindow.xib.

Image

Figure 6-7 UIApplication in the Document window

Image

Figure 6-8 AddViewProjectAppDelegate’s connections

3. Notice that the template automatically added the AddViewProjectAppDelegate object to the set of objects in the xib file (all of the objects are listed along the left side of the edit pane).

4. When you select the AddViewProjectAppDelete object and select the Connections pane, you will notice AddViewProjectAppDelegate’s window IBOutlet is set to the UIWindow in the nib (Figure 6-8). Also notice that the UIApplication’s delegate is set as AddViewProjectAppDelegate.

UIApplication and UIApplicationDelegate

Ignore UIApplication—you almost never modify it. Just know that UIApplication receives system events. It is your job to write code that handles those system events. You write that code in a class adopting the UIApplicationDelegate protocol. This protocol has several life cycle methods that handle application and system events. Table 6-1 lists UIApplicationDelegate’s methods. If you begin with a template, Xcode creates the class adopting the UIApplicationDelegate protocol for you, but Xcode does not implement the UIApplicationDelegate’s optional event-handling methods. For instance, in this chapter’s project, Xcode created the AddViewProjectAppDelegate.h and AddViewProjectAppDelegate.m files. The AddViewProjectAppDelegate class extends NSObject and adopts the UIApplicationDelegate.

@interface AddViewProjectAppDelegate : NSObject
<UIApplicationDelegate>

The application’s UIApplication, defined in MainWindow.xib, has a reference to its UIApplicationDelegate as an outlet (Figure 6-8). As UIApplication receives one of the events related to the methods in Table 6-1, it calls the appropriate method in its delegate if implemented.

The main.m File

In the AddViewProject project, open main.m in the Other Sources folder in the Navigation pane. The file’s code is listed in Listing 6-3.

Listing 6-3 File main.m in project

#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
     int retVal = UIApplicationMain(argc, argv, nil, nil);
     [pool release];
     return retVal;
}

Main creates one UIApplication instance using the UIApplicationMain method. Every project has exactly one UIApplication object. You can obtain a reference to that object by calling UIApplication’s sharedApplication class method. This method returns a singleton reference to your application’s UIApplication object.

UIApplication * myApplication = [UIApplication
        sharedApplication];

You usually will not do much with the UIApplication object other than obtain a reference to its UIApplicationDelegate. You obtain a reference to the UIApplicationDelegate through the following code:

UIApplicationDelegate * myDelegate = [[UIApplication
sharedApplication] delegate];

Handling Application Life Cycle Events

UIApplication forwards several important events to its UIApplicationDelegate to handle. For instance, applicationSignificantTimeChange: handles a significant time change while your application is running. The method didChangeStatusBarOrientation: handles the event fired when the status bar’s orientation is changed from portrait to landscape or landscape to portrait. The method didReceiveRemoteNotification: handles push notifications sent to your application. Table 6-1 lists UIApplicationDelegate’s application life cycle event-handling methods.

With the exception of application:didFinishLaunchingWithOptions:, the methods in Table 6-1 are not required, but you’ll need to implement many of them if you want to develop a robust, complete application. There are also four optional methods related to Apple’s Push Notifications that are beyond the scope of this book because they also require extensive support on the server side.

Two of the more important application life cycle events are your application’s startup and shutdown. The application:didFinishLaunchingWithOptions: method—a required method—is where you initialize your UIViewControllers, initialize your UIWindow, add a UIView to the window, and then launch your application’s user interface. The method is also useful for restoring your application’s state, and it is where you perform application initialization. The applicationWillTerminate: method is useful for saving your application’s state. You might also use this method to perform cleanup.

Image

Image

Table 6-1 UIApplicationDelegate Event-Handling Methods

TIP
Xcode offers a feature called Code Sense. As you are typing, Xcode will suggest what it thinks you are typing. If it is correct, press the TAB key and Xcode finishes typing for you. You can ignore the suggestion by continuing to type. If you are not certain the suggestion is correct, press CTRL-SPACE and Xcode presents a drop-down list with possible completions (Figure 6-9). Xcode 4 also added a Fix-it feature so that Xcode will highlight coding errors the same way a word processor would highlight spelling mistakes. If you do not see this feature, ensure Xcode is configured correctly in Xcode Preferences (Figure 6-10).

Application Interruptions

As your application functions, it is likely to receive interruptions. An incoming phone call causes your application to become inactive. If you decide to answer the call, your application terminates. Other events that might cause your application to become inactive include calendar alerts and putting your device to sleep (locking your device). The applicationWillResignActive: method in UIApplicationDelegate executes just prior to your application becoming inactive. The applicationDidBecomeActive: method executes just after your application becomes active again. For instance, if you are running your application and lock the screen, your application’s delegate executes the applicationWillResignActive: method. When you later unlock the screen, your application’s delegate executes the applicationDidBecomeActive: method.

Image

Figure 6-9 Code completion in Xcode

Image

Figure 6-10 Xcode Preferences

The applicationDidEnterBackground and applicationWillEnterForeground methods are available in iOS 4.0 and later to support applications that use background execution. This is Apple’s multitasking solution, and there are a number of requirements placed on your application if you want to do background processing. See the iOS Application Programming Guide for details.

Another important method is applicationDidReceiveMemoryWarning. iOS devices have limited memory—use too much and the operating system will terminate your application. But the operating system warns your application first. When UIApplication receives this event, it forwards the event to its delegate’s applicationDidReceiveMemoryWarning: method. The delegate can then handle the application’s response to the warning. For instance, it might release a shared data structure, empty and free image or data caches, or take other memory reclaiming actions.

CAUTION
Although this is not strictly required, your application should handle the events for becoming active/inactive and for low-memory situations in its UIApplicationDelegate. If it does not, Apple might reject your application when submitted for inclusion in the App Store.

Try This: Handling Application Interruptions

In this task, you explore the applicationDidReceiveMemoryWarning:, applicationWillResign Active:, and applicationDidBecomeActive: methods in UIApplicationDelegate.

1. Add the methods applicationDidReceiveMemoryWarning:, applicationDidBecomeActive:, and applicationWillResignActive: to AddViewProjectDelegate’s implementation (Add ViewProjectAppDelegate.m). Add a single NSLog statement to each method. The methods should appear similar to Listing 6-4.

Listing 6-4 AddViewProjectAppDelegate’s three additional methods

-(void)applicationDidReceiveMemoryWarning:(UIApplication *)
application { NSLog(@"hey got a memory warning....");
}
-(void)applicationWillResignActive:(UIApplication *) application {
NSLog(@"hey I'm about to resign active status....");
}
-(void)applicationDidBecomeActive:(UIApplication *) application {
NSLog(@"hey I'm active....");
}

2. Click Run, and execute the application in the iPhone Simulator.

3. Select Hardware | Simulate Memory Warning from the iPhone Simulator’s menu.

4. Select Hardware | Lock from the iPhone Simulator’s menu. Unlock and then quit your application.

5. Review the Debugger Console, which should appear similar to Listing 6-5.

Listing 6-5 Console output from running application

2010-08-25 11:24:24.147 AddViewProject[83787:207] hey I'm active....
2010-08-25 11:24:49.203 AddViewProject[83787:207] Received simulated
memory warning.

2010-08-25 11:24:49.203 AddViewProject[83787:207] hey got a memory
warning....
2010-08-25 11:25:02.356 AddViewProject[83787:207] hey I'm about to
resign active status....
2010-08-25 11:25:14.290 AddViewProject[83787:207] hey I'm active....
2010-08-25 11:25:17.336 AddViewProject[83787:207] hey I'm about to
resign active status....

The application executed the applicationDidBecomeActive: method when you started it and then after you unlocked the Simulator. It called applicationDidReceiveMemoryWarning: when you selected the Simulate Memory Warning menu item. And when the application was about to become inactive after locking, the UIApplicationDelegate executed the applicationWillResignActive: method.

Summary

The UIApplication is your application’s starting point. It is usually the first thing created by the main method in the main.m file. The application is always associated with a delegate. An application’s delegate is a class that implements the UIApplicationDelegate protocol. The delegate is where you place code for handling your application’s life cycle events.

A UIApplication has one UIApplicationDelegate. When using one of Xcode’s templates, the connection between the UIWindow, UIApplication, and UIApplicationDelegate is done for you in the MainWindow.xib nib file. Moreover, you almost never have to manually create a UIApplication and UIApplicationDelegate, as every project template creates these objects for you. You also do not need to worry about having main.m create the application, nor do you need to worry about implementing the application:didFinishLaunchingWithOptions: method, as these methods are almost always generated for you too.

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

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