Home / iPhone Tips and Tutorials

App Life Cycle

Although simple for the user, the birth, life, and death of an application is a pretty complex process. In this section, what happens throughout the time that the user launches the app from the Home screen, uses the app, and then stops using the app, either because she is done or decides to respond to an interruption such as a phone call or SMS message.

The life of an iPhone app begins when a user launches it by tapping its icon on the Home screen. The system launches your app by calling its main function, which you can see by opening the disclosure triangle next to the Supporting files group and selecting main.m in the Project navigator.

Tip:
The details of the implementation shown here may change, but the overall architecture will stay the same from iOS version to iOS version.
#import <UIKit/UIKit.h>
#import "RTAppDelegate.h"

int main(int argc, char *argv[])
{
  @autoreleasepool {
    return UIApplicationMain(argc, argv, nil,
	NSStringFromClass([RTAppDelegate class]));
  }
}

The main function is where a program starts execution. This function is responsible for the high-level organization of the program's functionality and typically has access to the command arguments given to the program when it was executed.

The main function does only two things:

  1. Sets up an autorelease pool:

    @autoreleasepool {

    This is a piece of memory-management plumbing that you don't need to use, or perhaps ever, but feel free to investigate on your own if you are interested.
  2. Calls the UIApplicationMain function to create the application object and delegate and set up the event loop:
    return UIApplicationMain(argc, argv, nil,
    		NSStringFromClass([RTAppDelegate class]));
    
    This is your entrance into the entire application startup process and its underlying architecture.

UIApplicationMain

The UIApplicationMain function creates the Application object (a singleton UIApplication object) and the Application Delegate (a class created for you by the Xcode template). It also sets up the main event loop, including the application's run loop (which is responsible for polling input sources) and begins processing events.

In the following section, explain the role of each of them in the application lifecycle.

UIApplication provides application-wide control

The UIApplication object provides the application-wide control and coordination for an iOS application. It is responsible for handling the initial routing of incoming user events (touches, for example) as well as for dispatching action messages from control objects (such as buttons) to the appropriate target objects. The application object sends messages to its Application Delegate to allow you to respond in an application-unique way to occurrences such as application launch, low-memory warnings, and state transitions such as moving into background and back into foreground.

Delegation is a mechanism used to avoid subclassing complex UIKit objects, such as the UIApplication object. Instead of subclassing and overriding methods in a framework or other object, you use that object unmodified and put your custom code inside a delegate object. As interesting events occur, the framework or other object sends messages to your delegate object. You use these methods to execute your custom code and implement the behavior you need. The delegation pattern more in "The Delegation pattern" section, later in this article.

The Application Delegate object is responsible for handling several critical system messages and must be present in every iOS application. The object can be an instance of any class you like, as long as it adopts the UIApplicationDelegate protocol. In the template you'll find it is a subclass of UIResponder, which enables it to respond to and handle events. (UIApplication is also derived from UIResponder.)

The methods of this protocol correspond to behaviors that are needed during the application life cycle and are your way of implementing this custom behavior. Although you aren't required to implement all the methods of the UIApplicationDelegate protocol, you'll often find yourself writing code to handle the following:

  • Initialization in your App Delegate's application:didFinish LaunchingWithOptions: method.
  • State transitions such as moving in and out of background and foreground. More detail in "The Normal Processing of Your Application Is Interrupted," later in this article.
  • Low-memory warnings, which cover in "Observing Low-Memory Warnings," later in this article.

The UIApplication is a singleton object (there is just one). To get a reference to it, you send the class message. (In Objective-C, you can send messages to classes, which are really objects on their own.) Sending the UIApplication object the delegate message gives you a pointer to the delegate object.

RTAppDelegate *appDelegate =
		[[UIApplication sharedApplication] delegate];

You'll be doing that a lot and it will become second nature to you.

UIApplicationMain loads the storyboard

If the application's Info.plist file specifies a storyboard file (or a main nib file), the UIApplicationMain function loads it. The application's Info.plist file provides a map to the high-level structure of the application.

To see the RoadTrip-Info.plist file, select RoadTrip-Info.plist in the Project navigator. The information in the file appears in the Editor area.

A nib file is a resource file that contains the specifications for one or more objects and is used to graphically create your user interface using Interface Builder in applications without a storyboard. (A storyboard consists of a series of linked nib files created for you.)

If you are using a storyboard, the initial view controller is instantiated. As you can see in in the Attributes inspector, that is a view controller property and is set for you by Interface Builder (you don't have to usually think about it).

UIApplication sends the application: didFinishLaunchingWithOptions: message to its delegate

If the method is implemented in the application delegate, the application: didFinishLaunchingWithOptions: message is sent to the App Delegate.

Launch time is a particularly important point in an application's lifecycle. In addition to the user launching an application by tapping its icon, an application can be launched to respond to a specific type of event. For example, it could be launched in response to an incoming push notification, it could be launched to open a file, or it could be launched to handle some background event that it had specified it wanted to handle (a location update for example). In all these cases, an options dictionary passed to the application: didFinishLaunchingWithOptions: method provides information about the reason for the launch.

The application:didFinishLaunchingWithOptions: message is sent to the delegate when the application has launched and its storyboard has been loaded. In this step, as you will see, you initialize and set up your application. At the time this method is called, your application is in the inactive state. At some point after this method returns, unless your application does some kind of background processing, your application will become active and will receive the applicationDidBecomeActive: message when it enters the foreground (becomes the application that the user sees on the screen), which I explain in "The Normal Processing of Your Application Is Interrupted" later in this article.

If your application was launched by the system for a specific reason, a launch Options dictionary contains data indicating the reason for the launch. An application launched by the system for a specific reason (other than the user tapping its icon).

Remember:
Your goal during startup is to present your application's user interface as quickly as possible - and quick initialization equals happy users. Don't load large data structures that your application won't use right away. If your application requires time to load data from the network (or perform other tasks that take noticeable time), get your interface up and running first and then launch the task that takes a longer time on a background thread. Then you can display a progress indicator or other feedback to the user to indicate that your application is loading the necessary data or doing something important.

In the templates that don't use a storyboard, you'll see that this method allocates and initializes the window and the initial view controller, adds it to the window, and makes the window visible, as follows:

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

In a storyboard-based application, this is all done by the storyboard for you, and the application:didFinishLaunchingWithOptions: is just a stub that does nothing other than return YES (the "usual" return).

You would return NO only if your application was launched because another application opened a URL that is owned by your application and your application cannot handle the URL.

[Contents] [Next]