Appendix A. Application Lifetime Events

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:
Received after application:didFinishLaunchingWithOptions:. Also received after the end of the situation that caused the app delegate to receive applicationWillResignActive:.
applicationWillResignActive:
One possibility is that something has blocked the app’s interface — for example, the screen has been locked. An alert dialog from outside your app, or an incoming phone call whose interface takes over the screen, could also cause this event. When this situation ends, the app delegate will receive 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:
The application has been backgrounded (and is about to be suspended). Always preceded by applicationWillResignActive:.
applicationWillEnterForeground:
The application was backgrounded (and suspended), and is now coming back to life. Always followed by 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:

The app launches freshly

Your app delegate receives these messages:

  • application:didFinishLaunchingWithOptions:
  • applicationDidBecomeActive:
The user clicks the Home button

If your app is frontmost, it will be suspended; before that, your app delegate receives these messages:

  • applicationWillResignActive:
  • applicationDidEnterBackground:
The user summons your backgrounded app to the front

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 double-clicks the Home button

The user can now work in the app switcher. If your app is frontmost, your app delegate receives this message:

  • applicationWillResignActive:
The user, in the app switcher, chooses another app

If your app was frontmost, your app delegate receives this message:

  • applicationDidEnterBackground:
The user, in the app switcher, chooses your app

If your app was the most recently frontmost app, then it was never backgrounded and suspended, so your app delegate receives this message:

  • applicationDidBecomeActive:
The user summons the control center or notification center

If your app is frontmost, your app delegate receives this message:

  • applicationWillResignActive:
The user dismisses the control center or notification center

If your app is frontmost, your app delegate receives this message:

  • applicationDidBecomeActive:
A local notification alert from another app appears

If your app is frontmost, your app delegate receives this message:

  • applicationWillResignActive:
From a local notification alert, the user launches the other app

Your app delegate receives these messages:

  • applicationDidBecomeActive:
  • applicationWillResignActive:
  • applicationDidEnterBackground:
The screen is locked

If your app is frontmost, your app delegate receives these messages:

The screen is unlocked

If your app is frontmost, your app delegate receives these messages:

The user holds the screen-lock button down

The device offers to shut itself down. If your app is frontmost, your app delegate receives this message:

The user, as the device offers to shut itself down, cancels

If your app is frontmost, your app delegate receives this message:

The user, as the device offers to shut itself down, accepts
If your app is frontmost, the app delegate receives no further messages. (This is a major change from earlier systems.)

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:.