UserDefaults sugar syntax

Emilien Stremsdoerfer
2 min readOct 29, 2017

--

UserDefaults is a pretty standard tool on iOS that you certainly had to use at some point. However, its syntax can be a bit heavy to use and doesn’t seem really Swifty sometimes. Let’s take a look at it.

Stringly typed

One big drawback of UserDefaults is that it uses strings to save and retrieve values.

Let’s be honest, you can get pretty lazy sometimes and you don’t feel like externalizing all your strings because, you know… you only need this here right? So you have something that looks like this:

let token = UserDefaults.standard.string(forKey: "token")

Now, first, this is not a super concise syntax, but even worse, let’s say that you were actually not that lazy in the first place and you externalized your key somewhere. You can end up with something like this.

let token = UserDefaults.standard.string(forKey: MyUserDefaultsKeys.User.Token)

You thought you were doing some good by externalizing your string but the code you now produce is actually quite less readable. And since it’s slightly less readable, you’re even less likely to adopt that style for the next values you’ll need to save. Bummer…

Not type safe

It feels a bit cumbersome to always have to specify what kind of type you want and to have different methods for this integer(forKey:) bool(forKey:) string(forKey:) . That seems not really Swifty and we feel like we could definitely do a better job using type inference or generics.

Also, have you ever thought about what would happen if you try to get an Int if you saved a String or a Bool in the first place? Answer is, sometimes it works, sometimes it doesn’t. Some types are compatible with each other and some aren’t. You don’t really want to be playing a guessing game all the time so that is not really ideal.

A Safer Syntax

Ideally, you would like to have a syntax that is concise and easy to use, so that you’d not feel lazy about using it. A syntax that is type safe so that you won’t have to worry about what kind of object you saved in the UserDefaults.

So let’s create a new structure that allows you to store and return an object from the UserDefault standard instance. And since we want it to be type safe, we can make it generic so that each pair carries its type.

Nice, now, let’s say that you have a Chat app and you want to save in UserDefaults pinned conversations and also a draft string for each conversation.

You can just create an extension of UserDefaults where you add every property that you want save. Every property defines the type of the object that will be saved to prevent you from misusing them.

Notice how the chatDraft pair is a closure that takes a parameter. This allows you to have dynamic keys which can be really useful. In this case, we define only one key for any draft.

Voilà! That was actually pretty easy, now you have a structure really easy to use, a lot more concise and safer than what you had before.

Here’s an example of how you would use it:

--

--

No responses yet