People naturally multitask on their devices. Whether they’re switching from app to app, bringing together apps on iPad using Slide Over or Split View, or creating multiple windows of the same app, they should be able to pick up right where they left off — and UI state restoration is a core part of making that experience seamless.
When your app goes out of view, the app’s process is typically put on pause; it’s not given any more CPU time, which keeps the processor free for other tasks. If your app has background processes that are running, the system can even terminate those if an active app needs more resources than currently available.
Restoring the state of your UI is a crucial part of making your app feel responsive — and it’s especially important if you plan to support multiple windows in your iPadOS app. If you have a note-taking app that has four different notes open in different Split View pairings, for example, state restoration helps preserve each note, rather than returning someone to the main screen when they open one of the windows.
NSUserActivity is a core part of modern state restoration with
UISceneDelegate: It provides a lightweight way to capture the state of your app and put it to use later, holding key information for both view controllers and important view states — information that can also be used when constructing view controllers for Handoff and Universal Linking.
While what you store in
NSUserActivity is up to you, we recommend collecting only the bare minimum so that your app can quickly restore itself. Think of the most unique and simple way you can identify your view controller, like a clear identifier or URL. Include that information, and make sure you can identify where the view controller lives in your navigation and how content should appear within it. For example, when using an Xcode storyboard you may want to store and retrieve view controllers using restoration IDs.
Get started with UI state restoration
The best way to implement UI state restoration is to make your app scene-based, which requires iOS 13, iPadOS 13, Mac Catalyst 10.13, or tvOS 13 or later. (For more information on working with scenes in your app, check out the Developer Library.) Here’s how to get started with scene-based state restoration:
- Create a
NSUserActivityobject to save the app’s state. This can be created in your scene delegate.
- In this
NSUserActivity, store relevant information (like the current navigation’s state, and view controllers that have been presented or pushed) along with your user’s intent.
- Return this
stateRestorationActivity(for:)in the scene delegate.
NSUserActivity will now be stored inside the scene’s
stateRestorationActivity property. When your app needs to restore its state, it should do so by looking for this saved
scene(_:willConnectTo:options:) in the scene delegate.
What about the older view controller-based state restoration APIs?
If you need to support older versions of iOS, macOS, or tvOS, you can use older view controller-based APIs for state restoration via restoration classes and the app delegate. This also means if you want to update your app to adopt UIScene as well as implement UI state restoration across multiple versions of iOS, you will need to implement both scene-based and view-controller based APIs. However, we highly recommend building scene-based UI state restoration.
Compared to the older APIs, modern state restoration requires a different approach to how you define, save, and restore your UI state and your user’s intent. With a scene-based app, you have to separate events in an application’s life cycle and the scene’s life cycle, which means tracking changes also differs. Having multiple scenes means there are many more windows to track, each with unique user actions and navigation history. For some of those windows, you may choose not to restore state depending on their function, requiring state restoration to be more flexible and dependent on how you define the user’s intent.
If you can update your app to scene-based restoration and take advantage of
NSUserActivity, you’ll also unlock easier pathways to implementing features like Spotlight search, Handoff, enabling Universal Links, and creating new scenes as primary or auxiliary windows. And you’ll provide a smoother and frictionless experience for people using your app, too.