State Restoration Tutorial: Getting Started
In this state restoration tutorial, learn how to use Apple’s State Restoration APIs to enhance a user’s experience of your app. By Luke Parham.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
State Restoration Tutorial: Getting Started
15 mins
Note: Updated for Xcode 7.3, iOS 9.3, and Swift 2.2 on 04-03-2016
State restoration is an often-overlooked feature in iOS that lets a user return to their app in the exact state in which they left it – regardless of what’s happened behind the scenes.
At some point, the operating system may need to remove your app from memory; this could significantly interrupt your user’s workflow. Your user also shouldn’t have to worry about switching to another app and losing all their work. This is where state restoration saves the day.
In this state restoration tutorial, you’ll update an existing app to add preservation and restoration functionalities and enhance the user experience for scenarios where their workflow is likely to be interrupted.
Getting Started
Download the starter project for this tutorial. The app is named Pet Finder; it’s a handy app for people who happen to be seeking the companionship of a furry feline friend.
Run the app in the simulator; you’ll be presented with an image of a cat that’s eligible for adoption:
Swipe right to be paired up with your new furry friend; swipe left to indicate you’d rather pass on this ball of fluff. You can view a list of all your current matches from the Matches tab bar:
Tap to view more details about a selected friend:
You can even edit your new friend’s name (or age, if you’re into bending the truth):
You’d hope that when you leave this app annd return to it later, you’d be brought back to the same furry friend you were last viewing. But is this truly the case with this app? The only way to tell is to test it.
Testing State Restoration
Run the app, swipe right on at least one cat, view your matches, then select one cat to view his or her details. Press Cmd+Shift+H to return to the home screen. Any state preservation logic, should it exist, would run at this point.
Next, stop the app from Xcode:
The state restoration framework intentionally discards any state information when the user manually kills an app, or when the state restoration process fails. These checks exist so that your app doesn’t get stuck in an infinite loop of bad states and restoration crashes. Thanks, Apple! :]
Note: You cannot kill the app yourself via the app switcher, otherwise state restoration simply won’t work.
Note: You cannot kill the app yourself via the app switcher, otherwise state restoration simply won’t work.
Launch the app again; instead of returning you to the pet detail view, you’re back at the home screen. Looks like you’ll need to add some state restoration logic yourself.
Enabling State Restoration
The first step in setting up state restoration is to enable it in your app delegate. Open AppDelegate.swift and add the following code:
func application(application: UIApplication, shouldSaveApplicationState coder: NSCoder) -> Bool {
return true
}
func application(application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
return true
}
There are five app delegate methods that manage state restoration. Returning true
in application(_:shouldSaveApplicationState:)
instructs the system to save the state of your views and view controllers whenever the app is backgrounded. Returning true
in application(_:shouldRestoreApplicationState:)
tells the system to attempt to restore the original state when the app restarts.
You can make these delegate methods return false
in certain scenarios, such as while testing or when the user’s running an older version of your app that can’t be restored.
Build and run your app, and navigate to a cat’s detail view. Press Cmd+Shift+H to background your app, then stop the app from Xcode. You’ll see the following:
It’s the exact same thing you saw before! Just opting-in to state restoration isn’t quite enough. You’ve enabled preservation and restoration in your app, but the view controllers aren’t yet participating. To remedy this, you’ll need to give each of these scenes a restoration identifier.
Setting Restoration Identifiers
A restoration identifier is simply a string property of views and view controllers that UIKit uses to restore those objects to their former glory. The actual content of those properties isn’t critical, as long as it’s unique. It’s the presence of a value that communicates to UIKit your desire to preserve this object.
Open Main.storyboard and you’ll see a tab bar controller, a navigation controller, and three custom view controllers:
Restoration identifiers can either be set in code or in Interface Builder. To make things easy, in this tutorial you’ll set them in Interface Builder. You could go in and think up a unique name for each view controller, but Interface Builder has a handy option named Use Storyboard ID that lets you use your Storyboard IDs for restoration identifiers as well.
In Main.storyboard, click on the tab bar controller and open the Identity Inspector. Enable the Use Storyboard ID option as shown below:
This will archive the view controller and restore it during the state restoration process.
Repeat the process for the navigation controller and the three view controllers. Make sure you’ve checked Use Storyboard ID for each of the view controllers, or your app may not restore its state properly.
Note that all the controllers already have a Storyboard ID and the checkbox simply uses the same string that you already have as Storyboard ID. If you are not using Storyboard IDs, you need to manually enter a unique Restoration ID.
Restoration identifiers come together to make restoration paths that form a unique path to any view controller in your app; it’s analagous to URIs in an API, where a unique path identifies a unique path to each resource.
For example, the following path represents MatchedPetsCollectionViewController:
RootTabBarController/NavigationController/MatchedPetsCollectionViewController
With this bit of functionality, the app will remember which view controller you left off on (for the most part), and any UIKit views will retain their previous state.
Build and run your app; test the flow for restoration back to the pet details view. Once you pause and restore your app, you should see the following:
Although the system restores the correct view controller, it appears to be missing the cat object that’s needed to populate the view. How do you restore the view controller and the objects it needs?