App Anatomy 101
The short-but-happy life of an iPad app begins when a user launches it by tapping its icon on the iPad Home screen. The system launches your app by calling its main function.
The main function does only three things:
- Sets up an autorelease pool:
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- Calls the UIApplicationMain function to create the application object
and delegate and set up the event loop. The template uses the first nil
as the principle class name so that UIApplication is the assumed
name, and it specifies the second nil to load the delegate object from
the application's main nib file:
int retVal = UIApplicationMain(argc, argv, nil, nil);
- At termination, releases the autorelease pool:
To be honest, this whole main function thing isn't something you even need to think about. What's important is what happens when the UIApplicationMain function is called. Here's the play-by-play:
- The main nib file is loaded.
A nib file is a resource file that contains the specifications for one or more objects. The main nib file usually contains a window object of some kind, the application delegate object, and any other key objects. When the file is loaded, the objects are reconstituted (think "instant application") in memory.
In the DeepThoughts app you just started (with a little help from the aforementioned View-based Application template), this is the moment of truth when the DeepThoughtsAppDelegate and DeepThoughtsViewController objects are created along with the main window.
- The application delegate (DeepThoughtsAppDelegate) receives the
The application:didFinishLaunchingWithOptions: message tells the delegate when the application has launched. In this step, you initialize and set up your application. You have a choice here: You may want to display your main application window as if the user were starting from scratch, or you may want the window to look the way it did when the user last exited the application. The application delegate object is a custom object that you code. It's responsible for some of the application-level behavior of your application.
- The UIKit framework sets up the event loop.
The event loop is the code responsible for polling input sources - the screen, for example. Events, such as touches on the screen, are sent to the object - say, a controller - that you have specified to handle that kind of event. These handling objects contain the code that implements what you want your app to do in response to that particular event. A touch on a control may result in a change in what the user sees in a view, a switch to a new view.
- The normal processing of your application is interrupted.
In iOS 4.2, your application must be able to handle situations where its normal processing is interrupted. The interruption may be temporary - for example, an incoming FaceTime call, calendar alerts, or the user pressing the Sleep/Wake button - or it may be a permanent one, such as when the user switches out of your app and your app begins the transition to its background state, where it's suspended to conserve power but remains in memory. iOS sends you a number of messages to let you know exactly what's happening and also give you the opportunity to do things such as save user data and state information - saving where the user was in the application.
Remember Saving is important, because whether the application is interrupted, sent to its background state, or terminated, when the time comes for it to launch again and the UIApplicationMain sends the application delegate the applicationDidFinishLaunching WithOptions message, you can restore the application to where the user left off.
- When the user performs an action that would cause your app to quit,
UIKit notifies your app and begins the termination process.
With iOS 4.2, the Terminator doesn't seek and destroy your app - it's simply moved to the inactive state and then the background state. (See "Responding to interruptions" in this tutorial.) But under some circumstances, your application can in fact be terminated.