Normal Processing of your Application is Interrupted
On an iPhone or iPod touch running iOS 4.2 or newer versions, various events besides termination can interrupt your app to allow the user to respond - for example, calendar alerts or the user pressing the Sleep/Wake button - and your app moves into the inactive state. If the user chooses to ignore an interruption, your app moves back into the active state and continues running as before. If the user decides to tap the alert to deal with it (or if the interruption was from the user touching the Home button to switch out of your application), your app the moves into its background state, where it is suspended to but remains in memory.
iOS sends you a number of messages to let you know exactly what's happening as well as to give you the opportunity to take actions such as save user data and state information, which means saving at the point where the user was in the application. (If an app needs to continue running, it can request execution time from the system.) Because the app is in the background (running or suspended) and still in memory, relaunching is nearly instantaneous. An app's objects (including its windows and views) remain in memory, so they don't need to be re-created when the app relaunches. If memory becomes constrained, iOS may purge background apps to make more room for the foreground app.
Because these interruptions cause a temporary loss of control by your app, touch events are no longer sent to your app. When developing your app, you need to take this fact into account. For example, if your app is a game, you should pause the game when your game is interrupted. In general, your app should store information about its current state when it moves to the inactive state and be able to restore itself to the current state upon a subsequent relaunch.
In all cases, the sequence of events starts the same way - with the applicationWillResignActive: message sent to your application delegate when the application is about to move from active to inactive state. In this method, you should pause ongoing tasks, disable timers, throttle down OpenGL ES frame rates (that is, you should use this method to pause the game), and generally put things on hold.
What happens after this depends on the nature of the interruption, and how the user responds to the interruption. Your application may be either moved to the background or reactivated.
Application is moved to the background
When the user accepts the notification or interruption, or clicks the Home button (or when the system launches another application), your application moves into the background state, where it is suspended. (If an app needs to continue running, it can request execution time from the system.)
The next two sections explain the messages your application can respond to when it is moved into background.
The applicationDidEnterBackground: message
When your app first enters the background state, it is sent the application DidEnterBackground: message. In this method, you should save any unsaved data or state (where the user is in the app - the current view, options selected, and stuff like that) to a temporary cache file or to the preferences database "on disk."
Remember
Even though your application enters the background state, you have no guarantee that it will remain there indefinitely. If memory becomes constrained, iOS will purge background apps to make more room for the foreground app. You need to do everything necessary to be able to restore your application in case it's subsequently purged from memory so that the next time the user launches your app, your application can use that information to restore your app to its previous state. You also have to do additional cleanup operations, such as deleting temporary files.
Warning
If your application is purged when it is in this suspended state, it receives no notice that it is removed from memory. You need to save any data beforehand!
When your delegate is sent the applicationDidEnterBackground: method, your app has an undocumented amount of time to finish things up. If the method doesn't return before time runs out (or if your app doesn't request more execution time from iOS), your app is terminated and purged from memory.
If your application requests more execution time or it has declared that it does background execution, it is allowed to continue running after the applicationDidEnterBackground: method returns. If not, your (now) background application is moved to the suspended state shortly after returning from the applicationDidEnterBackground: method.
If the application is in background it then may be relaunched. This can happen if the user selects the app from the Home screen or the Multitasking bar, or it is launched by the system if the app processes events in background or monitors a significant location change, for example.
The applicationWillEnterForeground: message is sent
When your application is relaunched from the background, it is sent the applicationWillEnterForeground: message. In this method, you need to undo what you did in the applicationDidEnterBackground: method (not applicationWillResignActive; you undo that next).
Your application is reactivated
If the user ignores the phone call, SMS, or calendar notification, or the app is relaunched from background, your application is reactivated and starts getting touch and other events.
When your application is reactivated, it is sent the applicationDidBecome Active: message.
You can use the applicationDidBecomeActive: method to restore the application to the state it was in before the interruption. Here you undo what you did in the applicationWillResignActive method, such as restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, you might need to refresh the user interface.
While an application is in the suspended state, the system tracks and coalesces events that might have an impact on that application when it relaunches. As soon as your application is up and running again, the system delivers those events to it. For most of these events, your application's existing infrastructure should just respond appropriately. For example, if the device orientation changed, your application's view controllers would automatically update the interface orientation in an appropriate way.
Your application is terminated
Apps are generally moved to the background when interrupted or when the user quits. But if the app was compiled with an earlier version of the SDK, or is running on an earlier version of the operating system that doesn't support multitasking - or if you decide that you don't want your app to run in the background and you set the UIApplicationExitsOnSuspend key in its Info.plist file - iOS terminates your app.
Remember
Even if your application supports multitasking (almost all do at this point), you must still be prepared for your application to be killed without any notification. The user can kill applications explicitly using the Multitasking bar. In addition, if memory becomes constrained, the system might remove applications from memory to make more room. If it does remove your suspended application, it does not give you any warning, much less notice! However, if your application is currently running in the background state, the system does call the applicationWillTerminate: method of the Application Delegate.
When your App Delegate is sent the applicationWillTerminate: in nonmultitasking applications, or those running in background, you need to do the same kinds of things you do in applicationDidEnterBackground:, except this time you do them knowing that your application will not be returning from background.
Your applicationWillTerminate: method implementation has a limited (albeit undocumented) amount of time to do what it needs to do and return. Any longer than that and your application is terminated and purged from memory. (The Terminator doesn't kid around.)
Overview of the View Controller Life Cycle
View controllers have a life cycle just as applications do, but I don't need to go into much detail about it here. The important part to know is that certain messages are sent as views that are displayed and hidden.
The two methods you need to know about in order to work with views are the following:
- viewDidLoad
- viewWillAppear:
The viewDidLoad message is sent to your RTViewController. This method is called after the view controller has loaded its associated views into memory. This method is used to perform view initialization and is not necessarily called every time the view appears. If, for example, the user makes a selection in the view that causes a new view controller to load and slide its view into place, and the user then taps the Back button, this message is not sent when the originating view reappears. That is the job of viewWill Appear:.
The viewWillAppear: message is sent when the view is about to become visible. The first time it is sent is after the viewDidLoad message and then whenever the view reappears, such as when you tap the Back button, for example. You use this method to refresh your user interface if needed, but not for initialization.
Numerous other methods are also placed in the RTViewController for you as stubs. Of course, aside from all this system stuff that happens, your application will be chugging along doing what the user wants it to do. And in responding to user requests, you'll create objects to do the user's bidding - which means that you allocate memory. And because memory is a scarce resource on the iPhone, you need to understand memory management, discussed in the next section.
In this tutorial:
- Runtime, Managing Memory, and Using Properties
- App Life Cycle
- Handling events while your application is executing
- Normal Processing of your Application is Interrupted
- Managed Memory Model Design Pattern
- Automatic Reference Counting
- Working with variable types according to ARC
- Low-Memory Warnings
- Framework Classes
- Understanding Declared Properties
- Hiding Instance Variables