Using Codables for Persisting Custom Objects in UserDefaults

Ahmad Fayyas
3 min readApr 28, 2019

Most of the apps we build require to persist data, leading to “What to use for data persistency?” It’s a crucial decision for setup the architectural layers for your apps, especially when recognizing there is a need to deal with “big” and/or “non-trivial structured” data; However, there are some of them require to persist a “small simple enough” data (one or two custom objects would be sufficient). Obviously, there are more than just one approach to follow for achieving such a task, for instance CoreData, Realm, SQLite, UserDefaults, writing data to JSON or plist files…

Hence you might think as:

Ugh! I don’t want to use a FULL (and possibly heavy) database for saving a single object or even couple of them!

I’d obviously agree this! Personally, I would avoid using CoreData (for instance) to persist a single object. Let’s take a look to a pretty simple approach, dealing with UserDefaults is simple enough right? 🙂

Codable to the rescue ⛑️

Back in days (and you might already know that), we dealt with NSCoding and NSKeyedArchiver/NSKeyedUnarchiver to persist custom objects. Nowadays (more specifically, starting from Swift 4), Codable makes our life easier for persisting custom objects! It might be similar to the approach of using NSCoding , but it is more natural when working with Swift and personally, I find it simpler.

Whatever, What’s the magic? ✨

As a reminder, Codable is a type alias for both Encodable and Decodable protocols, saying “we are going to use Codable” means that we will both encode and decode.

How it works: we encode the object therefore transforming it to Data , which is acceptable to be set in the UserDefault; For getting it back, we decode it back again into our custom type. That’s pretty much it!

Codables with UserDefault in action:

For demonstration, let’s apply this approach on implemented type. Consider that we have the following Employee struct that we need to persist its instances:

According to what mentioned for doing the “magic”, what do we need for now is to make Employee to be codable (conforms to Codable), simply as:

Note that Department also needs to conforms to Codable since Employee has a department property of type Department .

At this point, we can set any Employee instance into user defaults! Finally, we need to implement the methods for persisting/fetching an Employee instance into/from user defaults:

And we’re done!

You might ask

Since we are using JSONEncoder/JSONDecoder, are we dealing with JSON here?

Technically speaking, yes we do; However, you don’t have to bother yourself with thinking about how it works, the main part here is that you are working with aData instance and a custom type instance.

Let’s check it out:

Obviously, the ID should be different in your playground/project from the one on the code snippet, however it has to be identical for both the persisted and the fetched employee (technically, since they refer to the same employee) .

Again, if you still excited to see how see the JSON result for the persisted employee, you could add extra string declaration in the fetch method:

Certainly, john is editable (with variable var john):

Furthermore, What about a collection of custom objects?

Is the same approach applicable for a collection of codable objects? The good news is: Yes it is!

Let’s do it for Array :

As you can see, it’s almost the same functionality for persisting/fetching in the Employee struct, furthermore we are dealing with an array instead of a single instance.

Therefore:

Nicely works 👍.

⚠️ Here is a final note to keep in mind:

You should not persist sensitive data (such as passwords, credit card numbers, etc…) in the user defaults, still a public resource anyway. There are many articles out there talking about why you shouldn’t do it, you could check this one: https://www.andyibanez.com/nsuserdefaults-not-for-sensitive-data/.

--

--

Ahmad Fayyas

Software Engineer. If I’m not in front of my pc coding or playing video games, you can find me hanging out with family and friends, or sleeping!