Time to start moving away from pure Swift posts, and start talking about making iOS apps. Though we will be talking about doing so with Swift, of course. Today we are going to talk about the Five Execution states of an iOS app. The iOS operating system itself changes which state your app is in, and gives you a chance to make appropriate changes during most of the transitions.
The Five Execution States of an iOS App
Below I have included a small table describing the five execution states for an iOS app. The “Ground” collumn describe whether the app is in the Foreground or the Background in that execution state. The “Code” Column says whetehr that state is allowed to run code, or if the iOS operating system disallows it. Finally the “Events” column describes whether the app can respond to events like touches or accelerometer events (like shaking the phone).
State | Ground | Code | Events | Notes |
Not Running | N/A | App was either terminated or just hasn’t been launched. | ||
Suspended | Back | App is still in memory. | ||
Background | Back | X | App is running in background. Can be launched to this mode by system. | |
Inactive | Fore | X | Transitional state. App is either going to or coming from Active State. | |
Active | Fore | X | X | App is onscreen and running. |
Not Running
The simplest state your app can be in. It’s just not doing anything. Your iOS app can get into this execution state by the app being terminated (either by the system or by the user (by swiping it out of the multitasking pane), or by it just not being launched. This is definitely the case for when the app is first downloaded. It probably is also after a system reboot, but I am not certain of this yet (I could understand if it might load apps into memory that were before a reboot, but I do not know if it does).
Entrances: Suspended State or never being launched
Exits: Inactive or Background
Suspended
This is the state that your app is usually in when in the background. The app is still in memory, so it makes it easier to bring back to the Active State, but it is not running code so it does not affect battery life. When the system is low on memory, the app can be terminated from this execution state and moved to the Not Running state.
Entrances: Background
Exits: Background or Not Running
Background
This mode is where your app has been moved to the background, but is still able to run code. Your app can be launched directly to this mode if you ask the system to. This is may be from getting a push notification, such as if a podcast app was to download an episode so it is ready for the user later. Otherwise, the app is temporarily put into the Background execution state when it is removed from the foreground, giving you a little time to clean things up before the app is Suspended.
Entrances: Not Running, Inactive, or Suspended
Exits: Inactive or Suspended
Inactive
This state is generally just a transitional state. The only state that has access to the Active state is the Inactive state. To be in the Inactive state, your app is either becoming Active, or leaving the Active state to move to the background. It can run some code, but does not respond to touch or other events yet. This state can also be entered into if there is a system interruption, such as when the user receives a phone call.
Entrances: Not Running, Background, or Active
Exits: Background or Active
Active
This is the main execution state your app will be in when it is onscreen. If you are touching it and it is responding, it is in the Active state. In this state you can run code and respond to events. The only way to go to or from the Active state is through the Inactive state. If your app is not running, the path to get to the Active state is:
Not Running → Inactive → Active
If your app is Suspended, then the path to active is:
Suspended → Background → Inactive → Active.
When you press the home button, or switch to another app, your app is Suspended.
The path from Active to Suspended is:
Active → Inactive → Background → Suspended
As you can see from all of these different paths, the Active state can only be transitioned to or from the Inactive state.
Entrances: Inactive
Exits: Inactive
Handling Execution State Transitions
So, how do you handle these transitions and get your app ready for the next state it is going to? There are methods called in your app’s AppDelegate.swift file for several of these transitions. Also, each of these methods has an associated notification posted shortly after their associated methods are called.
applicationWillResignActive(application: UIApplication)
This method is triggered from the transition from Active to Inactive. In this method, you should pause any tasks that were running in the foreground. If you have played a game and been interrupted by receiving a phone call, you will usually come back to the game in some sort of paused state. Usually you would have to press the pause button manually, but well made games that are time based usually pause your game automatically when this happens. This method is what allows them to do this, or its associated Notification.
Associated Notification: UIApplicationWillResignActiveNotification
applicationDidBecomeActive(application: UIApplication)
This is the counterpart to the above method. This method is triggered on the transition from the Inactive to the Active State. Here you basically undo anything you did in applicationWillResignActive, at least when appropriate. Some games I could understand unpausing the game when you come back, but most I think should stay paused and allow the user to manually unpause, to give them more of a chance to respond to whatever is happing in the game after it is unpaused. If your app was in the Background, you would probably want to update the user interface here if appropriate (like if a social networking app grabbed new data in the Background that affects what should be onscreen).
Associated Notification: UIApplicationDidBecomeActiveNotification
applicationDidEnterBackground(application: UIApplication)
This method is triggered on the transition from Inactive to Background. You should probably save user state to disk here, if that is important to your app. After your app is put into the Background, unless you have requested background execution privileges, your app will be Suspended shortly thereafter. When it is Suspended, the system can terminate your app. When it does so, you are not alerted, and no method is called. That is why you should save your state here in this method, because it will probably be your last chance before a termination.
You could also release shared resources (like the Address Book, or a file) or shut down timers that were running in your application here as well.
Associated Notification: UIApplicationDidEnterBackgroundNotification
applicationWillEnterForeground(application: UIApplication)
This method is triggered on the transition from the Background state to Inactive. In general you should undo anything you did in applicationDidEnterBackground here. If you shut down timers or released resources, time to start the timers back up or attach to those resources again.
Associated Notification: UIApplicationWillEnterForegroundNotification
application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool
This method is called when you app is first launched after a termination. I have yet to find something explicitly saying in which state this happens, or at what transition. The UIApplicationDelegate Protocol Reference says that “This method is called after state restoration has occurred but before your app’s window and other UI have been presented. At some point after this method returns, the system calls another of your app delegate’s methods to move the state to the Active (foreground) state or the Background state.” As such, it appears to be somewhere around the transition from either Not Running to Inactive, or Not Running to Background transition (depending on whether the app is meant to open to the foreground or background).
Associated Notification: UIApplicationDidFinishLaunchingNotification
applicationWillTerminate(application: UIApplication)
This method is called on the transition from Background to Not Running. If the app is in the Background state, and the app is instructed to terminate (from the system or user), this method is called. It is not called if the app is terminated while in the Suspended state. You can save state here if you which, but since it is not called for apps in the Suspended state, it is probably best to save state in the applicationDidEnterBackground method.
Associated Notification: UIApplicationWillTerminateNotification
Conclusion
Thus begins our trek from pure Swift to the use of Cocoa Touch to make your iOS apps. Of course, we will be doing so in Swift, and covering new pure Swift topics as they come up, or I learn something particularly new (to me) that I think should be shared. I still have a few pure Swift topics on the docket though, but they will be interspersed with topics about iOS app development, like our discussion today.
While you may not interact with all of them in every app, you should still know about the five execution states for an iOS app. Even in my simple PregTracker app, I still had to handle updating the UI when the app switched from Suspended to Active. I found that sometimes when I opened the app, the main page would update the days along label, and sometimes it wouldn’t. I could force it to by going to another page and coming back, but that’s a terrible way to update the screen. I did not know about the five execution states at the time, but I soon found out. The times it did update when I opened the app, it was because the app needed to be relaunched, and thus it would call viewWillAppear which had my update code in it. However, the times it did not update when I opened the app, it turned out, were when the app had been Suspended, and was becoming active again. It didn’t call viewWillAppear when becoming active again, so the update code wasn’t called. I had this view controller subscribe to the UIApplicationWillEnterForegroundNotification (a notification called shortly after the similarly named method above), and call my update code when it received this notification. You can read about how I did this in Objective-C in my post Updating an app when returning from background in iOS.
I hope you found this article helpful. If you did, please don’t hesitate to share this post on Twitter or your social media of choice. The blog is still pretty new, and every share helps. Of course, if you have any questions, don’t hesitate to contact me on Twitter @CodingExplorer, and I’ll see what I can do. Thanks!