Your app’s one and only application object (a UIApplication instance, or on rare occasions a UIApplication subclass instance) is created for you as the shared application object by UIApplicationMain
, along with its delegate; in the Xcode project templates, this is an instance of the AppDelegate class. The application reports lifetime events through method calls to its delegate; other instances can also register to receive most of these events as notifications.
What application lifetime events you can receive depends on whether or not your app participates in multitasking. It almost certainly will. In the old days, before iOS 4, there was no multitasking. If the user pressed the Home button while running your app, your app was terminated. The next time the user launched your app by tapping its icon, your app launched from scratch. Even under iOS 7, your app can opt out of multitasking and behave like a pre–iOS 4 app, if you set the “Application does not run in background” key (UIApplicationExitsOnSuspend
) in your Info.plist. For some apps, such as certain games, this might be a reasonable thing to do.
In the multitasking world, however, the Home button doesn’t terminate your app; it backgrounds and suspends it. This means that your app is essentially freeze-dried in the background; its process still exists, but it isn’t actively running, and it isn’t getting any events — though notifications can be stored by the system for later delivery if your app comes to the front once again. If your app is terminated, it’s not because the user switches away from it, but because the system has killed it while it was suspended — for example, because it needed to reclaim the memory your suspended app was using, or because the user switched off the device.
(A backgrounded app can, however, continue to run certain specialized activities, such as playing music; and in iOS 7, a backgrounded app can be woken periodically in order to update its data via the network. See Chapters 14, 22, and 24. So a backgrounded app isn’t always necessarily completely suspended. But in general, most backgrounded apps are suspended most of the time.)
The suite of basic application lifetime events in the multitasking world is quite limited; indeed, in my opinion, the information your app is given is unfortunately rather too coarse-grained. The events are as follows:
application:didFinishLaunchingWithOptions:
The app has started up. You’ll typically perform initializations here. If an app doesn’t have a main storyboard, this code must also create the app’s window and show it.
In iOS 6 and iOS 7, another event, application:willFinishLaunchingWithOptions:
, arrives even earlier. Its purpose is to allow your app to participate in the state saving and restoration mechanism discussed in Chapter 6.
applicationDidBecomeActive:
application:didFinishLaunchingWithOptions:
. Also received after the end of the situation that caused the app delegate to receive applicationWillResignActive:
.
applicationWillResignActive:
applicationDidBecomeActive:
. Alternatively, the app may be about to go into the background (and will then be suspended); in that case, the next event will be applicationDidEnterBackground:
.
applicationDidEnterBackground:
applicationWillResignActive:
.
applicationWillEnterForeground:
applicationDidBecomeActive:
.
An additional event, applicationWillTerminate:
, was your last signal in the nonmultitasking world to preserve state and perform other final cleanup tasks. In the multitasking world, however, you’ll probably never get applicationWillTerminate:
, because by the time your app is terminated by the system, it was already suspended and incapable of receiving events.
The application lifetime events are best understood through some typical scenarios:
Your app delegate receives these messages:
application:didFinishLaunchingWithOptions:
applicationDidBecomeActive:
If your app is frontmost, it will be suspended; before that, your app delegate receives these messages:
applicationWillResignActive:
applicationDidEnterBackground:
Your app delegate receives these messages:
applicationWillEnterForeground:
applicationDidBecomeActive:
If the user summons your backgrounded app to the front indirectly, another delegate message may be sent between these two calls. For example, if the user asks another app to hand a file off to your app (Chapter 23), your app receives application:handleOpenURL:
between applicationWillEnterForeground:
and applicationDidBecomeActive:
.
The user can now work in the app switcher. If your app is frontmost, your app delegate receives this message:
applicationWillResignActive:
If your app was frontmost, your app delegate receives this message:
applicationDidEnterBackground:
If your app was the most recently frontmost app, then it was never backgrounded and suspended, so your app delegate receives this message:
applicationDidBecomeActive:
If your app is frontmost, your app delegate receives this message:
applicationWillResignActive:
If your app is frontmost, your app delegate receives this message:
applicationDidBecomeActive:
If your app is frontmost, your app delegate receives this message:
applicationWillResignActive:
Your app delegate receives these messages:
applicationDidBecomeActive:
applicationWillResignActive:
applicationDidEnterBackground:
If your app is frontmost, your app delegate receives these messages:
applicationWillResignActive:
applicationDidEnterBackground:
If your app is frontmost, your app delegate receives these messages:
applicationWillEnterForeground:
applicationDidBecomeActive:
The device offers to shut itself down. If your app is frontmost, your app delegate receives this message:
applicationWillResignActive:
If your app is frontmost, your app delegate receives this message:
applicationDidBecomeActive:
You can see what I mean when I say that this repertory of events is rather coarse-grained. applicationWillResignActive:
, for example, could indicate (among other things) that the user is summoning the app switcher, or that another application’s local notification alert has appeared in front of your app, or that the user is locking the screen, or that the user has single-clicked the Home button to leave your app altogether, or that a phone call has arrived while your app was frontmost, or that the user is about to shut down the device. But you can’t distinguish which of these things is happening.
Perhaps the most significant lifetime issue for your app is when to save information that might be lost, but must not be, if your app were terminated. In the nonmultitasking world, the last moment to do that was applicationWillTerminate:
. In the multitasking world, the last moment to do that used to be applicationDidEnterBackground:
, but in iOS 7 you won’t get that event if the user shuts down the device when your app is frontmost. This leaves only applicationWillResignActive:
.