Chapters

Hide chapters

SwiftUI Cookbook

Live Edition · iOS 16.4 · Swift 5.8.1 · Xcode 14.3.1

Using AppStorage & SceneStorage for Persistent State
Written by Team Kodeco

SwiftUI provides the AppStorage and SceneStorage property wrappers to facilitate the management of persistent state across your app. This section will guide you through the use of these wrappers, illustrating how to implement them in your code and providing examples of their applications.

SwiftUI’s AppStorage Property Wrapper

AppStorage is a property wrapper that allows you to read and write values from UserDefaults seamlessly. It’s an ideal tool for storing user preferences or other small bits of data that need to persist between app launches.

Let’s consider an example where you have a login screen, and you want to remember the username of the logged-in user. You can use the AppStorage property wrapper to achieve this:

struct ContentView: View {
  @AppStorage("username") var username: String = "Anonymous"

  var body: some View {
    VStack {
      Text("Welcome, \(username)!")

      Button("Log in") {
        username = "SuzGupta"
      }
    }
  }
}

Your preview should look like this:

Use the AppStorage property wrapper to work with UserDefaults.
Use the AppStorage property wrapper to work with UserDefaults.

In this code, @AppStorage("username") watches UserDefaults for a "username" key. Changing username will cause the new string to be written to UserDefaults immediately, while also updating the view. Please note, UserDefaults is not secure storage, so you should avoid saving any sensitive data using AppStorage.

SwiftUI’s SceneStorage Property Wrapper

SceneStorage is a property wrapper that you can use when you need automatic state restoration of a value. It functions in a manner similar to State, but its initial value is restored by the system if it was previously saved, and the value is shared with other SceneStorage variables in the same scene. The system manages the saving and restoring of SceneStorage data on your behalf. Each scene has its own notion of SceneStorage, so data is not shared between scenes.

However, SceneStorage should be used with lightweight data. Large data, such as model data, may result in poor performance if stored in SceneStorage. Additionally, if the scene is explicitly destroyed, the SceneStorage data is also destroyed.

Here’s an example of how SceneStorage can be used to save and restore the selected tab in a TabView:

struct ContentView: View {
  @SceneStorage("selectedTab") var selectedTab: String?

  var body: some View {
    TabView(selection: $selectedTab) {
      Text("Tab 1")
        .tabItem {
          Label("Tab 1", systemImage: "1.circle")
        }
        .tag("Tab1")

      Text("Tab 2")
        .tabItem {
          Label("Tab 2", systemImage: "2.circle")
        }
        .tag("Tab2")
    }
  }
}

Your preview should look like this:

You can use the SceneStorage property wrapper to save and restore the selected tab.
You can use the SceneStorage property wrapper to save and restore the selected tab.

In this example, the selectedTab variable is tagged with the @SceneStorage property wrapper, which means its value is automatically saved and restored across app launches or scene recreation. If the app is quit and relaunched, it will automatically select the tab that was last open.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.