Using static string constants for User Defaults

Daily Coding Tip 003

UserDefaults gives us access to an easy way to store data, but it has its limitations.

To quote Axel Lee’s website fluffy.es:

Using apps such as iExplorer, users can access the Library/Preferences folder of their iPhone and read / modify the UserDefaults plist data easily (eg: Change the boolean value of "boughtProVersion" from false to true, or change the amount of coins). Don't ever store a boolean for checking if user has bought in-app purchase in UserDefaults! User can change it very easily (without jailbreaking) and get your goodies for free! 😬

Other than in-app purchase status, you shouldn't store user password / API Keys in UserDefaults for the same reason as well.

Structured data belongs in CoreData, while sensitive data belongs in the keychain.

When storing simple data however, such as the name and age of a user in my case, UserDefaults works quite well.

As I established in Daily Coding Tip 002, raw strings are a dangerous thing. The compiler cannot help you if you make a spelling error, as a string can be given any spelling. This is especially true of UserDefaults, which relies on strings to save and load values to its property list. It’s easy to see how misspelling a key when saving can lead to a value being stored multiple times under multiple spellings of the key, and how attempting to load from a misspelled key can give the false impression that no value was set.

import SwiftUI
extension String {
static let nameKey = "nameKey"
static let ageKey = "ageKey"
}
struct ContentView: View {
@AppStorage(.nameKey) var name: String = ""
let age = UserDefaults.standard.integer(forKey: .ageKey)
var body: some View {
VStack {
Text("name: \(name)")
Text("age: \(age)")
}
}
}

Using an extension of String allows us to easily assign static constants. Although I’m using UserDefaults as an example, these could be used in any function or initializer that takes a String as a parameter. In SwiftUI I am loading from UserDefaults using the new @AppStorage property wrapper, which is new in iOS 14. This property wrapper requires a String for the key, and so I’m giving it my nameKey constant.

In any context outside of SwiftUI, it is necessary to do things the old-fashioned way.

I am loading my age property using UserDefaults.standard and my ageKey constant as a key.

It goes without saying that you must not make spelling mistakes in your constants, but that’s far less points of failure than every time you need to use them.

Get more Daily Coding Tips in your inbox!