emin
Posted on April 3, 2022
UserDefaults are not meant to hold huge amount of data or complex objects. We use CoreData for that.
But hey, sometimes we are just that lazy
Recently a twitter friend of mine Dan O'Leary asked how to save objects to UserDefaults and he seemed to like this extension, so I thought I could share it with all you awesome folks!
Did you know he has an app on the store as well? Check it out -> RunRooster
So, let's not dillydally and get right into it. Quiet in the back! 🤫
Preparation 🧩
First, let's create the object that we will be saving. A simple object you might use in the app.
struct UserSettings: Codable {
var userID: Int?
var modePreference: String?
var volumeLevel: Int?
var highScore: Int?
enum CodingKeys: String, CodingKey {
case userID = "id"
case modePreference = "mode_preference"
case volumeLevel = "volume_level"
case highScore = "highscore"
}
}
I added those CodingKeys as a bonus in case you are getting that info from the server as well. And snake_case is soooo last year. Ama right?
Now we got ourselves a nice UserSettings where we could hold on to some user....settings? 🥁
This is really useful if user changes some info but does not have a wi-fi or any other type of internet connection, so you can hold on to this object and send it at a later date.
Next, and this is not obligatory, we will create a separate object that holds all our keys. I made a mistake of using hand-typed strings for keys once...and never again. (stuff of nightmares)
struct Keys {
static let userSettings = "userSettings"
}
Execution 🤯🔫
Saving
Here comes the interesting bit. Let's create an extension that will save that object to UserDefaults.
extension UserDefaults {
static func saveUserSettings(_ settings: UserSettings) {
do {
let encodedUserSettings = try JSONEncoder().encode(settings)
UserDefaults.standard.set(encodedUserSettings, forKey: Keys.userSettings)
UserDefaults.standard.synchronize() // this line is a joke btw, read the summary, so awesome :)
} catch {
print("Error saving User Settings.")
}
}
//... loading code goes here
}
Thats it!
Quite easy right? Now you know why some developers (myself included) really love to use this quick and dirty way of saving some small objects for later use.
Loading
Same as the above, but in reverse ⏪
//... saving code
static func loadUserSettings() -> UserSettings? {
guard let settings = UserDefaults.standard.object(forKey: Keys.userSettings),
let loadedSettings = settings as? Data else {
return nil
}
return try? JSONDecoder().decode(UserSettings.self, from: loadedSettings)
}
The only difference is that here our return is optional. Maybe we still haven't saved anything, who knows 🤷♂️
All jokes regarding laziness aside, keep in mind that UserDefaults size DOES affect you app loading time, and should only be used for smaller objects. Also, saving a user password there is a giant NO-NO.
Hope that helps on your future coding endeavours!
Thank you for reading, you lovely person! ♥️ Lets hook up on [Twitter][twitter]?
Posted on April 3, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.