How to Use User Defaults in Swift

Download Your Free Copy of
The Missing Manual
for Swift Development

The Guide I Wish I Had When I Started Out

Join 20,000+ Developers Learning About Swift Development

Download Your Free Copy

The defaults system is the easiest persistence solution on iOS, tvOS, macOS, iPadOS, and watchOS. A defaults database is nothing more than a key-value store. You interact with the defaults system through the UserDefaults class. Let's take a look at the API of the UserDefaults class.

Shared Defaults Object

Most applications interact with the shared defaults object. You access the shared defaults object through the standard class property.

import Foundation

// Access Shared Defaults Object
let userDefaults = UserDefaults.standard

The user's default database is written to disk as a property list or plist. A property list or plist is an XML file. The UserDefaults class keeps the contents of the property list in memory while your application is running to improve performance. It loads the property list once and writes any changes you make to disk.

Reading or Getting Values From User Defaults

The API of the UserDefaults class is easy to use in Swift. The most basic API to read or get values from the user's defaults database in Swift is object(forKey:). This method returns a value of type Any?, an optional. As I mentioned earlier, the defaults database is a key-value store. The UserDefaults class looks up the value for the key that is passed to the object(forKey:) method and returns a value if a value exists for the given key. It returns nil if no value exists for the given key.

import Foundation

// Access Shared Defaults Object
let userDefaults = UserDefaults.standard

// Read/Get Value
userDefaults.object(forKey: "myKey")

The UserDefaults class also defines a number of convenience methods for retrieving values of a specific type. To access the boolean value for a given key, you invoke bool(forKey:). If no key-value pair can be found for the given key, bool(forKey:) returns false.

import Foundation

// Access Shared Defaults Object
let userDefaults = UserDefaults.standard

// Read Boolean
let value = userDefaults.bool(forKey: "myKey")

Know that bool(forKey:) is a convenience method. The following expression has the same result, but it is less elegant and more verbose.

import Foundation

// Access Shared Defaults Object
let userDefaults = UserDefaults.standard

// Read Boolean
let value = userDefaults.object(forKey: "myKey") as? Bool ?? false

Writing or Setting Values To User Defaults

Creating or updating a key-value pair is trivial. You simply invoke the set(_:forKey:) method on the UserDefaults instance. In this example, we set the value of myKey to true by invoking the set(_:forKey:) method on the shared defaults object.

import Foundation

// Access Shared Defaults Object
let userDefaults = UserDefaults.standard

// Write/Set Value
userDefaults.set(true, forKey: "myKey")

Data Types

It is essential that you know which data types can be stored in the defaults database. You can only store a predefined list of data types, that is, strings, numbers, Date objects, and Data objects. You can also store arrays or dictionaries of these types. In this example, we define a struct with name User and create a User object with name Bart. We then pass the User object to set(_:forKey:) method of the UserDefaults class.

import Foundation

struct User {

    let name: String

}

// Create User
let user = User(name: "Bart")

// Write User to User's Defaults
UserDefaults.standard.set(user, forKey: "user")

This won't work. If you run this example in a playground, a runtime exception is thrown. Why is that? The user constant is of type User. Remember that only strings, numbers, Date objects, and Data objects can be stored in the user's defaults database.

Storing a Custom Object in User Defaults Does Not Work | Runtime Exception

You can store custom objects in the defaults database with a workaround, though. I explain that in this post.

When to Use User Defaults?

The defaults system is a good fit if you need to store small amounts of data that don't need to be secured. For sensitive information, such as a username or an access token, I strongly recommend using the keychain. Even though you can store any type of data as binary data in the user's defaults database, this approach isn't recommended if you need to store large amounts of data.

Download Your Free Copy of
The Missing Manual
for Swift Development

The Guide I Wish I Had When I Started Out

Join 20,000+ Developers Learning About Swift Development

Download Your Free Copy