Saving objects to UserDefaults
Tags: swift, ios, iphone, xcode
Published: 2022-04-03 17:24:25

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

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ya4auxb5at1b44o86fdu.png)

Recently a twitter friend of mine [Dan O'Leary][dan] 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][dansApp]

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.

```swift
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)

```swift
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*.

```swift
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 ⏪ 

```swift
//... 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 🤷‍♂️

---

<p class="info">
All jokes regarding laziness aside, keep in mind that UserDefaults size <strong>DOES</strong> affect you app loading time, and should only be used for smaller objects. Also, saving a user password there is a giant <strong>NO-NO</strong>.
</p>

Hope that helps on your future coding endeavours! 

---

Thank you for reading, you lovely person! ♥️ Lets hook up on [Twitter][twitter]?

[dan]: https://twitter.com/olearydan
[dansApp]: https://apps.apple.com/us/app/run-roster/id1496557315