The UserDefaults class has a fairly extensive API that should meet most of your needs. From time to time, however, you need to perform a task that is less trivial. How do you clear the user's defaults database? The UserDefaults class doesn't offer this functionality. What options do you have to reset the user's defaults database in Swift?

Reset Standard User Defaults

The documentation of the UserDefaults class lists a method in the Legacy section that seems to do the trick. The method is named resetStandardUserDefaults(). Don't get your hopes up, though. The description of the method says "This method has no effect and shouldn't be used." Let's put that to the test. Create a playground, add the following code snippet, and run the contents of the playground.

import Foundation

// Write/Set Boolean in User Defaults
UserDefaults.standard.set(true, forKey: "myKey")

// Before Resetting User Defaults
print("before", UserDefaults.standard.bool(forKey: "myKey"))

// Reset Standard User Defaults
UserDefaults.resetStandardUserDefaults()

// After Resetting User Defaults
print("after", UserDefaults.standard.bool(forKey: "myKey"))

The output in the console confirms that the resetStandardUserDefaults() method has no effect. It doesn't clear or reset the user's defaults database.

before true
after true

Removing a Key-Value Pair

To remove a key-value pair from the user's defaults database, you need to invoke removeObject(forKey:) on the UserDefaults instance. Let's update the previous example.

import Foundation

// Write/Set Boolean in User Defaults
UserDefaults.standard.set(true, forKey: "myKey")

// Before Resetting User Defaults
print("before", UserDefaults.standard.bool(forKey: "myKey"))

// Remove Key-Value Pair
UserDefaults.standard.removeObject(forKey: "myKey")

// After Resetting User Defaults
print("after", UserDefaults.standard.bool(forKey: "myKey"))

The output in the console confirms that the removeObject(forKey:) method works as advertised.

before true
after false

Removing Every Key-Value Pair

The removeObject(forKey:) method also works fine if you need to remove multiple key-value pairs. For that to work, you need to carefully keep track of the data you store in the user's defaults database. There are several solutions to accomplish this. Let's take a look at one of them.

We start by defining an extension for the UserDefaults class. In the extension, we create a enum with name Keys and String as the raw value. The Keys enum manages the keys used to store data in the user's defaults database.

import Foundation

extension UserDefaults {

    enum Keys: String {

        case unitsNotation
        case temperatureNotation
        case allowDownloadsOverCellular

    }

}

We conform the Keys enum to the CaseIterable protocol. Why is this necessary? If we conform the Keys enum to the CaseIterable protocol, a computed property with name allCases automatically becomes available. This computed property returns an array that includes every case the Keys enum defines. This comes in useful in a few moments.

import Foundation

extension UserDefaults {

    enum Keys: String, CaseIterable {

        case unitsNotation
        case temperatureNotation
        case allowDownloadsOverCellular

    }

}

With the Keys enum in place, we can implement an instance method with name reset(). The implementation requires a single line of code. We ask the Keys enum for the array of cases using the allCases computed property. We use the forEach(_:) method to loop over the array of cases. We invoke the removeObject(forKey:) method on the UserDefaults instance, passing in the raw value of the case. That's it.

import Foundation

extension UserDefaults {

    enum Keys: String, CaseIterable {

        case unitsNotation
        case temperatureNotation
        case allowDownloadsOverCellular

    }

    func reset() {
        Keys.allCases.forEach { removeObject(forKey: $0.rawValue) }
    }

}

It goes without saying that this solution only works if you diligently use the Keys enum in the rest of the project. Let's take a look at an example.

import Foundation

extension UserDefaults {

    enum Keys: String, CaseIterable {

        case unitsNotation
        case temperatureNotation
        case allowDownloadsOverCellular

    }

    func reset() {
        Keys.allCases.forEach { removeObject(forKey: $0.rawValue) }
    }

}

// Write/Set Boolean in User Defaults
UserDefaults.standard.set(true, forKey: UserDefaults.Keys.allowDownloadsOverCellular.rawValue)

print("before", UserDefaults.standard.bool(forKey: UserDefaults.Keys.allowDownloadsOverCellular.rawValue))

// Reset User Defaults
UserDefaults.standard.reset()

print("after", UserDefaults.standard.bool(forKey: UserDefaults.Keys.allowDownloadsOverCellular.rawValue))

Run the contents of the playground and inspect the output in the console. We use the Keys enum to set the value of the allowDownloadsOverCellular key to true. The first print statement confirms that this works. We then invoke the reset() method to clear the user's defaults database. The second print statement confirms that the reset() method works as expected.

before true
after false

Room for Improvement

We could further improve the solution by adding convenience properties for each of the settings, but that is beyond the scope of this post. You can read more about that technique in another post.