{"id":116778,"date":"2020-04-22T18:37:15","date_gmt":"2020-04-22T18:37:15","guid":{"rendered":"https:\/\/developer.apple.com\/news\/?id=4ixc0yxs"},"modified":"2020-04-22T18:37:15","modified_gmt":"2020-04-22T18:37:15","slug":"how-to-implement-ui-state-restoration","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2020\/04\/22\/how-to-implement-ui-state-restoration\/","title":{"rendered":"How to implement UI state restoration"},"content":{"rendered":"<div class=\"inline-article-image\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/08\/how-to-implement-ui-state-restoration.jpg\" data-hires=\"false\"><\/div>\n<p>People naturally multitask on their devices. Whether they\u2019re 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 \u2014&nbsp;and UI state restoration is a core part of making that experience seamless.<\/p>\n<p>When your app goes out of view, the app\u2019s process is typically put on pause; it\u2019s 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.<\/p>\n<p>Restoring the state of your UI is a crucial part of making your app feel responsive \u2014&nbsp;and it\u2019s 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.<\/p>\n<div class=\"inline-article-image\" readability=\"33\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/08\/how-to-implement-ui-state-restoration-1.jpg\" data-hires=\"false\"><\/p>\n<p class=\"typography-caption\">Two different types of scenes can be backgrounded and processes halted. These scenes\u2019 states should be saved to restore later.<\/p>\n<\/div>\n<h3>Meet NSUserActivity<\/h3>\n<p><code>NSUserActivity<\/code> is a core part of modern state restoration with <code>UIScene<\/code> and <code>UISceneDelegate<\/code>: 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 \u2014 information that can also be used when constructing view controllers for <a href=\"https:\/\/developer.apple.com\/documentation\/foundation\/task_management\/implementing_handoff_in_your_app\">Handoff<\/a> and <a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/inter-process_communication\/allowing_apps_and_websites_to_link_to_your_content\">Universal Linking<\/a>.<\/p>\n<p>While what you store in <code>NSUserActivity<\/code> 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.<\/p>\n<h3>Get started with UI state restoration<\/h3>\n<p>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 <a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/app_and_environment\/scenes\">Developer Library<\/a>.) Here\u2019s how to get started with scene-based state restoration: <\/p>\n<ol>\n<li>Create a <code>NSUserActivity<\/code> object to save the app&#8217;s state. This can be created in your scene delegate.<\/li>\n<li>In this <code>NSUserActivity<\/code>, store relevant information (like the current navigation\u2019s state, and view controllers that have been presented or pushed) along with your user\u2019s intent.<\/li>\n<li>Return this <code>NSUserActivity<\/code> within <code>stateRestorationActivity(for:)<\/code> in the scene delegate.<\/li>\n<\/ol>\n<div class=\"inline-article-image\" readability=\"32\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/08\/how-to-implement-ui-state-restoration-2.jpg\" data-hires=\"false\"><\/p>\n<p class=\"typography-caption\">You need to collect the right information in each UIScene to pick up where someone left off.<\/p>\n<\/div>\n<p>This <code>NSUserActivity<\/code> will now be stored inside the scene\u2019s&nbsp;<code>stateRestorationActivity<\/code> property. When your app needs to restore its state, it should do so by looking for this saved <code>NSUserActivity<\/code> under <code>scene(_:willConnectTo:options:)<\/code> in the scene delegate.<\/p>\n<p><strong>What about the older view controller-based state restoration APIs?<\/strong> <\/p>\n<p>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.<\/p>\n<p>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\u2019s intent. With a scene-based app, you have to separate events in an application\u2019s life cycle and the scene\u2019s 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\u2019s intent.<\/p>\n<div class=\"inline-article-image\" readability=\"33\"><img decoding=\"async\" src=\"https:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2020\/08\/how-to-implement-ui-state-restoration-3.jpg\" data-hires=\"false\"><\/p>\n<p class=\"typography-caption\">Prior to the introduction of UIScene, each app had a singular life cycle.<\/p>\n<\/div>\n<p>If you can update your app to scene-based restoration and take advantage of <code>NSUserActivity<\/code>, you\u2019ll 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\u2019ll provide a smoother and frictionless experience for people using your app, too.<\/p>\n<hr>\n<h3>Resources<\/h3>\n<p><a href=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2019\/258\/\">Watch \u201cArchitecting your app for multiple windows\u201d<\/a><\/p>\n<p><a href=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2019\/259\/\">Watch \u201cTargeting content with multiple windows\u201d<\/a><\/p>\n<p><a href=\"https:\/\/developer.apple.com\/videos\/play\/wwdc2019\/246\/\">Watch \u201cWindow management in your multitasking app\u201d<\/a><\/p>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/view_controllers\/preserving_your_app_s_ui_across_launches\">Learn more about restoring state in non-scene <span class=\"icon icon-after icon-chevronright nowrap\">based apps<\/span><\/a><\/p>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/uikit\/uiviewcontroller\/restoring_your_app_s_state\">Explore sample code for restoring your app\u2019s state<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>People naturally multitask on their devices. Whether they\u2019re 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 \u2014&nbsp;and UI state restoration is a core part of making that [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":116779,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[55],"tags":[],"class_list":["post-116778","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-apple-developer-news"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/116778","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=116778"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/116778\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/116779"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=116778"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=116778"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=116778"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}