How To: Setting And Getting Data With UserDefaults In Swift

Written by: Reinder de Vries, September 19 2017, in App Development

How To Setting And Getting Data With UserDefaults In Swift

The UserDefaults object, formerly known as NSUserDefaults, is exceptionally useful for storing small pieces of data in your app. You use it to save your app user’s settings, set some “flags”, or simply use it as a tiny data store.

In this article you’ll learn:

  • How to set and get data with UserDefaults
  • When it’s best to use the user defaults (and when not…)
  • How the user defaults work and how to use them to improve your iOS development

Ready? Let’s go.

  1. What Are UserDefaults?
  2. Saving Data in UserDefaults
  3. Getting Data from UserDefaults
  4. When to Use UserDefaults
  5. Further Reading

What Are UserDefaults?

So what are these UserDefaults?

The user defaults is a .plist file in your app’s package and you can use it to set and get simple pieces of data. It’s structure is very similar to that of a dictionary and the user defaults are often regarded as a key-value store.

Quick Note: Before Swift 3, the UserDefaults class was known as NSUserDefaults. Swift 3 removed many of these “NS” prefixes.

A key-value store (“KVS”) is, as the name says, a way to assign a value to certain keys. Like this:

var dict = [
    "name": "John Doe",
    "language": "English",
    "occupation": "Carpenter"
]

A dictionary: On the left you see keys, and on the right you see values. When you want to get to John’s name, you simply do:

print(dict["name"])
// Output: John Doe

When you want to change John’s occupation, you simply do:

dict["occupation"] = "Engineer"

Quite simple, right? User defaults with the UserDefault class is not much different.

Internally, the user defaults are saved in a .plist file. A property list file (hence, “plist”) is a dictionary saved in a column-row format, like this:

The dictionary structure is still clearly visible: you see keys on the left, and values on the right. The most common .plist file in any app is of course the Info.plist, that contains many basic settings of your app, like it’s name and Bundle ID.

When you check out the documentation for the UserDefaults class you’ll see that the class has several important functions:

  • init() function and standard property for initializing the user defaults
  • object(forKey:), url(forKey:), string(forKey:), bool(forKey:) etc. for getting values from the defaults
  • set(_:forKey:) for storing values in the user defaults, and removeObject(forKey:) to remove them
  • synchronize() to write the user defaults to disk, or to update them from the disk

In the next chapters you’ll check out all of these functions. Let’s continue!

Note: Why are they called “user defaults”? Although it’s not official, I’ve always regarded the user defaults as “the default settings, configurations and data an app user start the app with”. It’s kind of a little set of data that’s available right from the start of the app, that you use to store simple and general config info.

Get 5 of my best practices

Get 5 of my best practices

Learn how to build better iOS apps

I’ll show you exactly how I built a dozen professional iOS apps,
write extensible Swift code, and turn coffee into code.
Wait, what? Yup – into Swift code.

Saving Data in UserDefaults

Let’s first look at saving data in the user defaults. You can save a number of simple variable types in the user defaults:

  • Booleans with Bool, integers with Int, floats with Float and doubles with Double
  • Strings with String, binary data with Data, dates with Date, URLs with the URL type
  • Collection types with Array and Dictionary

Internally the UserDefaults class can only store NSData, NSString, NSNumber, NSDate, NSArray and NSDictionary classes. These are object types that can be saved in a property list. You can also tell by the “NS” prefix that they are part of the Objective-C framework Foundation.

Before you can save data in the user defaults you need to grab a reference to the user defaults. In most cases you can work with the standard property, like this:

UserDefaults.standard

In the example above, you use the class variable standard, which is available anywhere in your code, to get hold of the “standard user defaults”.

You can also create your own user defaults, called a persistent domain, which you can read more about in the documentation.

So, when you want to save something, you simply do this:

let name = "John Doe"
UserDefaults.standard.set(name, forKey: "name")

In the above example you’re assigning the variable name to the key "name" in the user defaults, effectively creating this key-value pair:

{
    "name": "John Doe"
}

As you’ve seen in the official documentation, that set(_:forKey:) takes a number of types as its first argument, as long as they can be saved in a property list file.

Quick Tip: Do you want to save one of your own object types, like Vehicle or Person? Make sure to adopt the NSCoding protocol, then encode your object to a Data object, save it in the user defaults, and then decode it again when you need it later on. Also, always check if this is data you really want to store in the user defaults…

Then, when you want to remove that value from the user defaults you simply call:

UserDefaults.standard.removeObject(forKey: "name")

You can also overwrite an object that you’ve previously set:

UserDefaults.standard.set("Arthur Dent", forKey: "name")

Whenever you’ve changed the user defaults you need to synchronize them, to make the changes persist on the disk.

The user defaults are represented in the iPhone’s memory as a dictionary, and they remain there when your app is running, so when you want your data to persist between app launches, you need to synchronize them. When you do that, the data is saved on the iPhone’s disk.

Synchronizing is quite simple:

UserDefaults.standard.synchronize()

You’ll often see the following code block when working with multiple user defaults values:

var defaults = UserDefaults.standard
defaults.set("Arthur Dent",     forKey: "name")
defaults.set(42,                forKey: "age")
defaults.set("English",         forKey: "language")
defaults.set("Hazardous",       forKey: "occupation")
defaults.synchronize()

See how the user defaults are first assigned to a separate local variable, then set one by one, and finally synchronized? It saves you from writing all that UserDefaults.standard... every time!

Now that you’ve saved your values, let’s see how you can get them back…

Build better iOS apps by mastering best practices and app architecture » Find out how

Getting Data from UserDefaults

Getting data from the user defaults is just as simple as saving it. Here’s how you get the value associated with the key "name":

let name = NSUserDefaults.standard.string(forKey: "name")
print(name)
// Outputs: Arthur Dent

It’s worth noting here that these getters will return optional values, so the type of name is String?. When the "name" key doesn’t exist, the above code returns nil.

It then makes sense to use optional binding to get the value safely:

if let name = NSUserDefaults.standard.string(forKey: "name") {
    print(name)
}

You can also use the nil-coalescing operator ?? to provide a default value:

let name = NSUserDefaults.standard.string(forKey: "name") ?? "Unknown user"

Just like with saving the user defaults, you can save yourself some time typing, and make your code clearer, if you assign the standard user defaults to a temporary local variable:

let defaults    = NSUserDefaults.standard
let name        = defaults.string(forKey: "name") ?? "Unknown user"
let occupation  = defaults.string(forKey: "occupation") ?? "Unknown"
let age         = defaults.int(forKey: "age") ?? 0

You may have noticed that the functions you use to get values from the user defaults can return values with an explicit type. The one function that can return values for any type is object(forKey:), which will return values with the type Any?.

These functions are url(forKey:), array(forKey:), dictionary(forKey:), string(forKey:), stringArray(forKey:) (with type [String]?), data(forKey:), bool(forKey:), integer(forKey:), float(forKey:), and double(forKey:).

Logically, when you’re retrieving a value as Int, but it’s stored as a String, the returned value is nil.

The user defaults are already synchronized when you start your app, but if you work with them at multiple points in your app, and you need to refresh your data, you can call synchronize() before you start getting values from the user defaults to force it to refresh.

So… when do you actually need to use the user defaults?

How to use UserDefaults to set and get data in Swift Click To Tweet

When to Use UserDefaults

The user defaults are best used for simple pieces of data. If you need to store multiple objects of the same type it’s smarter to use an actual database, like Realm.

Examples are:

  • User information, like name, email address, age, occupation
  • App settings, like user interface language, app color theme or “detailed vs. simple UI”
  • Flags, more on this later

It’s important to always check whether a data point can, or should be, saved somewhere else. Many back-end frameworks, for instance, already have storage in place to save a current user’s information. The app’s language is saved in the iPhone’s locale settings.

One smart way to use user defaults are flags. They are boolean values (true or false) that indicate whether some event or setting has already happened. Examples:

  • If the user already has completed the app’s onboarding, with "hasOnboarded"
  • If the user has already upgraded the in-app database, with "databaseUpgraded"
  • If the user is one of your app’s initial beta testers, and should get an upgrade for free, with "isBetaTester_2013"

You can also use flags for more complex data points, like dates:

  • When the user last updated the app, and you can then show a message to update the app to a better supported version
  • When the last cloud sync date was, and sync when the gap is too big
  • When the last time the user was asked for feedback on the app

It’s always important to think through the possible scenarios when working with flags, because it’s easy to make mistakes. One way of keeping track is to create a simple flow diagram showing the different flags, states and defaults you’re using in your app. You can then easily spot if your app can get to an unsupported state, and then change your code accordingly.

Get 5 of my best practices

Get 5 of my best practices

Learn how to build better iOS apps

I’ll show you exactly how I built a dozen professional iOS apps,
write extensible Swift code, and turn coffee into code.
Wait, what? Yup – into Swift code.

Further Reading

So, that’s all there is to setting and getting data with UserDefaults! It’s a small, neat data store you can use to save simple settings. Always investigate what storage tool to use for your specific use case.

Want to learn more? Check out these resources:

Do you have questions about UserDefaults? Let me know in the comments section, below!

Reinder de Vries

Reinder de Vries is a professional iOS developer. He teaches app developers how to build their own apps at LearnAppMaking.com. Since 2009 he has developed a few dozen apps for iOS, worked for global brands and lead development at several startups. When he’s not coding, he enjoys strong espresso and traveling.

Comments & Questions

Got a comment or question? Let me know! I read and respond to every one. Thanks!