How to use UserDefaults in Swift

UserDefaults are meant to be used to store small pieces of data which persist across app launches. It is very common to use UserDefaults to store app settings or user preferences. UserDefaults lets you store key-value pairs, where a key is always a String and value can be one of the following data types: Data, String, Number, Date, Array or Dictionary. This tutorial will show you how to use UserDefaults in Swift.

UserDefaults saves its data in a local plists file on disk. UserDefaults are persisted for backups and restores. Currently there is no size limit for data on platforms other than tvOS (which is 1MB).

In order to start using UserDefaults, first, get the standard user defaults object:

let defaults = UserDefaults.standard

Writing data to UserDefaults

In order to set the UserDefaults, use one of its set(_:forKey:) instance methods.

Set the value of “userAge” key to an integer value:

defaults.set(22, forKey: "userAge")

Set the value of “darkModeEnabled” key to a boolean variable:

var darkModeEnabled = true
defaults.set(darkModeEnabled, forKey: "darkModeEnabled")

Set the value of “favoriteFruits” key to an array of strings:

let fruits = ["Apple", "Banana", "Mango"]
defaults.set(fruits, forKey: "favoriteFruits")

Set the value of “toggleStates” key to a Swift dictionary:

let toggleStates = ["WiFi": true, "Bluetooth": false, "Cellular": true]
defaults.set(toggleStates, forKey: "toggleStates")

Reading data from UserDefaults

In order to get data from UserDefaults, use one of its type dedicated get methods, or a generic object(forKey:) method.

Get the integer value associated with the “userAge” key:

let userAge = defaults.integer(forKey: "userAge")

Get the boolean value associated with the “darkModeEnabled” key: 

let darkModeEnabled = defaults.bool(forKey: "darkModeEnabled")

Get the array of strings associated with the “favoriteFruits” key:

let favoriteFruits = defaults.array(forKey: "favoriteFruits”)

Note that the return value of the above array method is an optional. Nil will be returned if the given key does not exist or if its value is not an array.

Get the dictionary associated with the “toggleStates” key:

let toggleStates = defaults.dictionary(forKey: "toggleStates")

Providing a default value in absence of a default

What if there is no object associated with the given key? We already covered a case when using the array method which will return nil. You have to be careful when using other get methods because some of them might surprise you. For example, when using the integer(forKey:) method, it returns 0 in absence of the specified key.

In order to unify this behavior across your app, you can always use the object(forKey:) method when reading data from UserDefaults. It guarantees you to return nil in case the given key is absent.

Let’s take a look at an example of using a nil coalescing operator in Swift to set a default value in case the given key doesn’t exist:

let favoriteFruits = defaults.object(forKey: "favoriteFruits") as? [String] ?? [String]()

If the “favoriteFruits” key is missing in UserDefaults, instead of returning nil, the above code sets the favoriteFruits constant to an empty array of strings.

Storing custom objects in UserDefaults

Define a custom structure to model a user of your app:

struct User: Codable {
    let name: String
    let age: Int
}

Make sure that the struct conforms to the Codable protocol which will allow to convert itself to other representations (such as Data).

Create an instance of a user, use a JSONEncoder() to covert it to Data and save it to UserDefaults:

let user = User(name: "Swift Guide", age: 22)

let encoder = JSONEncoder()
if let encodedUser = try? encoder.encode(user) {
    defaults.set(encodedUser, forKey: "user")
}

Reading custom objects from UserDefaults

First, try to get an object from UserDefaults and cast it to Data, then use a JSONDecoder() to convert the Data to a custom User type. If successful, print the saved user object:

if let savedUserData = defaults.object(forKey: "user") as? Data {
    let decoder = JSONDecoder()
    if let savedUser = try? decoder.decode(User.self, from: savedUserData) {
        print("Saved user: \(savedUser)")
    }
}

Related tutorials: