All You Need to Know About the iOS App Lifecycle (Part 1)
An iOS app has several different states it can be in between launch time and termination. Let's get an overview of the different states by looking at the figure below:
From this, we see that the app can either exist in the foreground, background or not be running.
- Foreground (green section): the app is the user's focus of attention and can receive UI events.
- Background (blue section): the app is not visible but is still running code for a limited time.
- Not running (no section): the app is not running any code at all.
Besides these, the app transitions between individual states (transitions shown with arrows in the figure). We can hook into these transitions in our code and execute appropriate state handling as transitions happen. Most notably in our app's AppDelegate. We'll look much more into handling of state changes in the next post. For now, our focus is to understand each state change.
Not running to inactive
Let's start by looking at our first state change, going from "not running" to "inactive". During "not running", no process is running our app. It's not getting any CPU cycles. An obvious way of getting out of this state is by launching the app. This takes our app from "not running" and to the foreground in the "inactive" state. The "inactive" state is when the app is running but not receiving UI events. The app is still getting started up. The app resides in this state briefly, before it's fully launched and enters the "active" state. Here, the app is ready to receive events.
As previously mentioned, handling of state changes can be done in the AppDelegate. During this state change, the following AppDelegate method gets called:
func application(UIApplication, will/didFinishLaunchingWithOptions: [UIApplication.LaunchOptionsKey:Any]?)
As we see from this method, a dictionary is passed in. This lets you know why your app was launched. A reason for this could be that you pressed the app icon. But there are tons of other ways an app can get launched. For instance, CoreLocation provides functionality for launching the app if the user walks within certain set of coordinates.
If you use the NotificationCenter to listen for state change you would add an observer of the following notification:
If you're unfamiliar with NotificationCenter. Don't worry, I'll get to this in the next post.
Active to inactive
The next transition we'll look at is going from "active" to "inactive". This could happen if we implement pausing in our app and show a pause menu. Another reason might be that a phone call comes in. Or simple when our app is on the way to be thrown to the background. In any case, we should handle it by performing a pause. For instance, in a game we would display a pause menu.
The method we would implement in the AppDelegate is this:
If you'd rather listen for state change in your view controller, here's the notification:
Inactive to active
The transition from "inactive" to "active" is relevant, when you need to unpause your app. This is where you'd close the pause menu and reactivate things. It will also be triggered whenever you hang up a phone call that initially paused your app. Let's look at the AppDelegate method that gets called:
And using NotificationCenter you can observe the following notification:
Foreground to background
When someone exits your app by pressing the home button, you app will be moved to the background. Now it time to be respond to this state change quickly, as you only get to run for about 30 seconds at this point. This means that you should hurry and clean up, as you could get suspended and afterwards killed at any time. It is possible to request more time, but don't abuse this (or the system will kill you instead).
Looking at the AppDelegate, the method you'd implement is:
Or simply observe the following notification:
Background to foreground
Phew, you app didn't get killed as the user made your app active again. Now, let's bring things back up and undo what whatever we did when entering the background. You know the drill by now. The AppDelegate method to look at is:
And you can observe this notification:
Background to suspended
After a little while of being backgrounded, your app gets suspended. This means no code running at all. Your app's process still exists but it's not getting CPU cycles. When suspended your app can get killed at any point in time. So if you got any last words, you should implement the following AppDelegate method:
Or simply listen for this notification:
This was part 1 of 2 in this short series of posts about the iOS app lifecycle. We touched upon the entire iOS app lifecycle from launch to termination. We looked at all the state changes that we can handle in our code, through our AppDelegate or by listening for the given notification. In the next part, we'll take a closer look at how we use code to react to state changes.
Thanks for reading. Remember to leave a comment and share with your fellow developers.
Share this post
You may also like
A common frustration with the iOS platform is that resources are accessed using magic strings. In practice, this means you’ll find out if an image, icon, localized string etc. exists at runtime. Either by seeing what you were hoping for or getting a hard crash. Let’s fix this by introducing your new best friend – R.swift.
RxSwift is well known for having a steep learning curve. But taking the time to learn it can easily be the next significant leap in your development abilities. We’ll cover the basic concepts of the library to quickly get you up to speed.
Framing your App Store screenshots greatly improves your store listing. But doing it manually takes hours away from perfecting your app. Instead, here’s how you automate the process of adding device frames and text to your screenshots.