Blue gradient with a database symbol on the center.

Storing information using User Defaults and @AppStorage

Learn the different ways of persisting small pieces of data in your app with UserDefaults.

If you want to persist data in your app across launches there are multiple strategies that you can adopt. If you have complex data to store with relationships between different entities you should consider adopting the CoreData or SwiftData framework. If you need to store information inside your app folder you can use FileManager. When it comes to persisting simple information like user preferences you can consider adopting UserDefaults.

UserDefaults

UserDefaults is a class in Swift that enables persistent storage of a small amount of data across app launches. It supports fundamental data types such as Bool, Int, Double, String, Data, and URL. By using a key-value pair system, UserDefaults simplifies the storing and retrieval of specific data across your code.

In this example, we will explore how to use the UserDefaults class in a SwiftUI app to store essential information such as the number of books read so far.

Screenshot of an app with a label on the center with a number, a label with saying "number of books read so far" and a button that adds one to the number

UserDefaults is great for storing small data bits like user preferences or settings. Still, it’s not designed for large amounts of data because everything you store in UserDefaults will automatically be loaded when your app launches. Remember that you should not store sensitive information there because it’s not encrypted.

Accessing the UserDefaults

The UserDefaults class uses a key-value pair system, which means that every time you store something using it you need to specify a key. To access UserDefaults, we use its shared instance.

UserDefaults.standard

Writing data using UserDefaults

To write data you need to use the set(_:forKey:) method. It associates a value to a key, so you can use it to have access to it when needed.

UserDefaults.standard.set(false, forKey: "isOnboardingShown")

Reading data using UserDefaults

To read data you need to use the object(forKey:) method specifying the key associated with the value you want to retrieve.

let isOnboardingShown = UserDefaults.standard
		.object(forKey: "isOnboardingShown") as! Bool

This method will return the value as of type Any?, but different versions return the value directly as the type you expect it to be. They are all listed on the documentation page.

let isOnboardingShown = UserDefaults.standard
		.bool(forKey: "isOnboardingShown")

The @AppStorage property wrapper

SwiftUI provides a property wrapper that simplifies the implementation of UserDefaults in a SwiftUI View.

With the @AppStorage property wrapper, accessing the UserDefaults system becomes straightforward. It simplifies the process of reading and writing data to it, automatically updating the view whenever the stored value changes. It also acts as a @State variable, triggering changes in the view.

Here is an example implementation of the @AppStorage property wrapper in a SwiftUI view:

import SwiftUI

struct ContentView: View {
    
    @AppStorage("bookCounter") var bookCounter = 0
    
    var body: some View {
        NavigationStack{
            VStack {
                Spacer()
                Text("\\(bookCounter)")
                    .font(.largeTitle)
                Text("Number of books read so far")
                    .font(.title3)
                    .padding()
                Spacer()
                
                Button(){
                    bookCounter += 1
                } label: {
                    Label("Add a book", systemImage: "book")
                }.buttonStyle(BorderedProminentButtonStyle())
            }
            .navigationTitle("Book Tracker")
            .toolbar(){
                ToolbarItem(){
                    Button(){
                        bookCounter = 0
                    } label: {
                        Image(systemName: "arrow.counterclockwise.circle.fill").foregroundStyle(.black)
                    }
                }
            }
            .padding()
        }
        
    }
}

We declared a property bookCounter with the @AppStorageproperty wrapper, using "bookCounter" as the UserDefaults key and a default value.

When we access or modify bookCounter, it reads from and writes to the UserDefaults with the key "bookCounter." If there’s an existing value saved in UserDefaults with the matching key, it will be displayed inside the View.

Privacy Update

Starting from May 1, 2024, it’s crucial to specify why our app relies on the UserDefaults API. This information needs to be included in the privacy manifest file inside our Xcode project.

You can find more information on the Documentation:

Describing use of required reason API | Apple Developer Documentation
Ensure your use of covered API is consistent with policy.