Working with UserDefaults in iOS

Working with UserDefaults in iOS

UserDefaults provides a database to store data and it is available as long as the app is installed.

Features

  • The UserDefaults class provides access to the user's defaults database.

  • It stores data persistently across the app launches as long as the app is installed.

  • Access to the data is private to the app unless shared through App Groups.

  • Access to this database is thread-safe.

  • It is a key-value store that works through a property list (plist) file.

  • Supported data types include String, Bool, Date, Array, Dictionary, Data and Numbers.

  • Custom objects can be stored by encoding them as data.

  • We can use this to store non-sensitive data such as user preferences.

Usage

Utilising the default shared instance of UserDefaults.

import Foundation
// Set a key value in UserDefaults
UserDefaults.standard.set("Shivam", forKey: "firstname")
// Get a key value from User Defaults
UserDefaults.standard.value(forKey: "firstname")
// Empty User Defaults
UserDefaults.standard.removeObject(forKey: "firstname")

Creating a UserDefaults that can be shared with multiple apps and extensions.

import Foundation
// User Defaults with Suite.
// Useful for sharing data with other apps
// or extensions with app groups.
let defaults = UserDefaults(suiteName: "group.com.organisation.appname")! 
// Set a key value in User Defaults
defaults.set("Shivam", forKey: "firstname") 
// Get a key value from User Defaults
defaults.value(forKey: "firstname") 
// Empty User Defaults
defaults.removeObject(forKey: "firstname")

Storing custom objects in UserDefaults.

import Foundation
// Custom model to be stored in UserDefaults
struct Student: Codable {
    let firstname: String
    let lastname: String
    let grade: Int
    let subjects: Array<String>
    let teachers: [String: String]
    let profileImage: Data
    let dateModified: Date
}

// Student Object
let student = Student(firstname: "John",
                      lastname: "Doe",
                      grade: 2,
                      subjects: ["Hindi", "English", "Maths"],
                      teachers: ["Hindi": "Teacher A", "English": "Teacher b", "Maths": "Teacher X"],
                      profileImage: Data(),
                      dateModified: Date())

// Encode custom object to data and store it in UserDefaults
let encoder = JSONEncoder()
do {
    let data = try encoder.encode(student)
    UserDefaults.standard.setValue(data, forKey: "StudentData")
} catch {
    throw error
}

// Retrieve data from UserDefaults and decode it to custom object
let decoder = JSONDecoder()
if let data = UserDefaults.standard.value(forKey: "StudentData") as? Data {
    do {
        let object = try decoder.decode(Student.self, from: data)
        print(object)
    } catch {
        throw error
    }
} else {
    print("No data in UserDefaults.")
}

Using UserDefaults as a Property Wrapper

Check out this gist to use UserDefaults with Property Wrapper. This is a more generalized way to use in Projects.