When you go to lunch and leave something on your desk, you expect that everything will remain in place after your return. Your user expect’s the same when he presses the “Home” button on his iPhone or receives a phone call. He expects to open application and find application in the same state, as it was left.
Application state preserving is often skipped by developers. To make user happy we must care about application state saving and restoring.
What is it
The application state is restored, when user is able to continue to work with it as after waking from background. Restoration means both Appearance and Behavior. Which generally means, that user will not only see the view he saw last before application went to background, but will be able to navigate through the same navigation stack as he left.
State preservation is
ViewController based. The UI architecture of your app is based on
ViewControllers and relations between them. So
ViewController is the main unit of application state restoration.
You control whether you want to restore some states or not. You can mark some
ViewController for restoration, or just skip it. No problem.
State pereserving is Incremental development compatible. If you decided to incorporate it into your application, you can do it step by step. No need to do some extreme changes and rewrite whole product.
Apple did a lot of effort to make it easy for developers. iOS handles the accounting and provides default, easy adoptable behaviors and does almost all hard work of looping through views, recreating navigation stack, saving state and e. t. c.
Handle the semantics
Applications are built for users. Try to look at your application from the users point of view. Notice, which parts of the work are importand for restoring and define the restoration level. When your application is a book reader, you want to start reading exactly from the place you finished. If application has difficult navigation stack, then you probably want to restore it to prevent user to repeat navigation. Everything is up to you. To you as user.
Mark your application parts for restoring
First of all, you must inform the system, that it should handle state saving. You can do it in
AppDelegate by adding the following methods. Their names are pretty verbose, so we will not stop on them. You may not want to restore state, for instance, after application version update. Then just use conditions to make them return
For more complex restoring scenarios
AppDelegate contains three more methods
The state preservation system calls this method at the beginning of the preservation process. This is your opportunity to add any app-level information to state information. For example, you might use this method to write version information or the high-level configuration of your app.
The state restoration system calls this method as the final step in the state restoration process. By the time this method is called, all other restorable objects will have been restored and put back into their previous state. You can use this method to read any high-level app data you saved in the
application:willEncodeRestorableStateWithCoder: method and apply it to your app.
During state restoration, when
UIKit encounters a view controller without a restoration class, it calls this method to ask for the corresponding view controller object. Your implementation of this method should create (or find) the corresponding view controller object and return it. If your app delegate does not provide the view controller, return nil.
It is not always necessary to create a new view controller object in your implementation of this method. You can also return an existing view controller object that was created by another means. For example, you would always return the existing view controllers loaded from your app’s main storyboard file rather than create new objects.
I already told, that state saving is
ViewController based. Generally it means, that you should mark needed
ViewControllers for restoration by adding restoration identifiers. It can be done using interface builder or code. To mark code based
ViewController for restoration you must set
viewDidLoad() method. Right after calling
If your app is Storyboard based, then you can do it from XCode as it shown on the fig. 1, by inputing the Restoration ID or just putting a Use Storyboard ID checkmark. Actually, in the most of cases i suggest second option;
Implement save/restore methods
ViewController with a restoration identifier will receive a call
encodeRestorableStateWithCoder(_:) of the
UIStateRestoring protocol when the app is saved. When the app is restored,
ViewController will receive
decodeRestorableStateWithCoder(_:) call. Though you may need to equip these methods with your custom logic.
After navigation stack and view controllers recreation you may need to restore your views, present some data or e. t. c.
Important! Do not save your model/view on state saving/restoration!
UIViewController conforms to
UIStateRestoring protocol. If your
ViewController has Restoration ID,
UIKit will call the following method to save state, when application goes to background:
UIKit will attemt to restore, it will call
Once you’ve decoded stored objects,
applicationFinishedRestoringState() method will be fired.
To restore code-based
Tips and Tricks
Apple strongly recommens to follow these guidelines when implementing state restoration:
As you add support for state preservation and restoration to your app, consider the following guidelines:
Encode version information along with the rest of your app’s state. During the preservation process, it is recommended that you encode a version string or number that identifies the current revision of your app’s user interface. You can encode this state in the
application:willEncodeRestorableStateWithCoder:method of your app delegate. When your app delegate’s
application:shouldRestoreApplicationState:method is called, you can retrieve this information from the provided coder and use it to determine if state preservation is possible.
Do not include objects from your data model in your app’s state. Apps should continue to save their data separately in iCloud or to local files on disk. Never use the state restoration mechanism to save that data. Preserved interface data may be deleted if problems occur during a restore operation. Therefore, any preservation-related data you write to disk should be considered purgeable.
The state preservation system expects you to use view controllers in the ways they were designed to be used. The view controller hierarchy is created through a combination of view controller containment and by presenting one view controller from another. If your app displays the view of a view controller by another means—for example, by adding it to another view without creating a containment relationship between the corresponding view controllers—the preservation system will not be able to find your view controller to preserve it.
Remember that you might not want to preserve all view controllers. In some cases, it might not make sense to preserve a view controller. For example, if the user left your app while it was displaying a view controller to change the user’s password, you might want to cancel the operation and restore the app to the previous screen. In such a case, you would not preserve the view controller that asks for the new password information.
Avoid swapping view controller classes during the restoration process. The state preservation system encodes the class of the view controllers it preserves. During restoration, if your app returns an object whose class does not match (or is not a subclass of) the original object, the system does not ask the view controller to decode any state information. Thus, swapping out the old view controller for a completely different one does not restore the full state of the object.
The system automatically deletes an app’s preserved state when the user force quits the app. Deleting the preserved state information when the app is killed is a safety precaution. (As a safety precaution, the system also deletes preserved state if the app crashes twice during launch.) If you want to test your app’s ability to restore its state, you should not use the multitasking bar to kill the app during debugging. Instead, use Xcode to kill the app or kill the app programmatically by installing a temporary command or gesture to call exit on demand.
Where to go from here?
First of all, this article does not cover
View states preserving. This topic is well covered here. For better understanding i recommend you to check the sources mentioned in the bottom of the article.
Saving application state across launches is relatively cheap, but very important thing, if your goal is creating high quality applications. UI state restoration is a tool with wide possibilities. You can yse it to remember tge selected tab, or to fully recreate the UI across launches.