Swift: Property wrappers

property wrapper

Property wrappers enable you to reuse code that specifies the access pattern of a property.

Often you add behaviour to a property through its observers. For example, you can use the didSet observer to trim a string:

This is very useful. However, if you want to add this behaviour to several properties, you have to implement this behaviour separately for each property. Instead, you can define a so called property wrapper.

You create a property wrapper by creating a struct, class or enum that uses the @propertyWrapper annotation. Inside the property wrapper you have to implement the wrappedValue property. By implementing property observers of wrappedValue you can add custom behaviour.

Note that observers of stored properties (didSet, willSet) get not called at initialisation time. Hence, you also have to implement the init method.

Let’s create a property wrapper for the use case of trimming a string:

A property wrapper can then be applied to every property that has the corresponding type:

As you can see, you just have to add the annotation @WhiteSpacesTrimmed.

wrappedValue as a computed property

In the last example, the wrapped value was a stored property. It’s also possible to use a computed value:

In this example we created a property wrapper that limits an integer property to the maximum value of 100.

Customizing a property wrapper

As you have seen in the last example, a property wrapper can have properties of its own. But it’s also possible to initialise these properties with custom values every time you use the property wrapper.

In the following example we create a property wrapper that writes and saves a string value to the user defaults. The name of the user defaults key is customizable:

If your property wrapper has properties, they can be initialised. If they have an initial value, they’re are optional. If they lack an initial value, they are mandatory.

Projected values

Besides wrappedValue there is another special property inside a property wrapper: projectedValue. This value is accessible from the outside by using the symbol $. Hence, you can use it to provide additional functionality.

In the following example we again create a property wrapper that trims a string. But in this case we save the initial value inside the projectedValue property:

References

Title image: @ Foxys Forest Manufacture / shutterstock.com