Swift - UserDefaults and @PropertyWrapper.

Thibault Carpentier
2 min readJun 6, 2020

--

Swift 5 introduces a new tool that developers can use when creating properties. The propertyWrapper. The property wrapper offers many opportunities for developers to make their code, more readable, reusable and maintainable. Let’s study this more in-depth through a use case that would apply to most of the iOS codebase.

@PropertyWrapper, what is it?

A property wrapper adds a layer of separation between code that manages how a property is stored and the code that defines a property.

A propertyWrapper can be implemented using either a struct, a class, or even an enum by annotating it with the @propertyWrapper attribute. The only requirement is that each property wrapper type should contain a stored property called wrappedValue, which tells Swift what underlying value is being wrapped.

UserDefaults Study Case

In a lot of applications, an easy way to save locally some user preferences is to leverage UserDefaults. We can imagine the following is being stored in UserDefaults:

Here is a somewhat clean wrapper we could have for an application. We can see that everything is stored in static variable in a struct, and that some properties have default values. The problem is that outside of the key and the default value, our code is repeated… a LOT. On top of this, it’s pretty hard to scan quickly for the default values. And that file can grow to be much bigger depending on how many properties you are storing.

PropertyWrapper to the rescue

Let’s try to leverage the new property wrapper tool here to make it a bit more simple. From what we see here, we need to provide for each property, a default value, and a key.

Let’s create a property wrapper for the Int type:

Here is the final implementation for the Int related attributes. Let’s break it down a bit

Line 3–4 are creating a new propertywrapper struct.

The struct declares two properties, defaultValue and Key. The wrappedValue allows conformance to the propertyWrapper type and implements the UserDefaults get and set operation, leveraging my two other parameters.

You can now see that the actual key definition looks way cleaner and easier to use on line 14–15.

This is great and all, but we’ve only solved for the Int type. We can do better here. Let’s leverage generics to modify a bit our class.

Here it is, by adding a Wrappedgeneric type definition to our type, we can now use this generic in the defaultValue and wrappedValue (l 6–7) and in our conditional casting on line 8 too. This small wrapper is now the only place where the Userdefaults code is being used, so we got rid of the code duplication. We also allowed for a much clearer and easy to use DataToSave property definition.

Going further

This small exemple is just a glimpse on how powerful the property wrapper can really be. They can allow for way more use case, like thread protecting the access to a property, performing validation or adjustment to a value, syncing a value to a database or with a server, and much more!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet