A property wrapper lets us define property access patterns that can be applied repeatedly.

What does that mean? In essence, the property wrapper is a data structure that provides controlled access to the property that uses it as a wrapper.

In this article, I show you how to define a property wrapper and how to apply it. I’m also going to show you a practical example of using property wrappers.

Alright, let’s dig in!

To define the most basic property wrapper, create a structure, class or enumeration and mark it using the @propertyWrapper attribute:

@propertyWrapper

struct Box {
}

The property wrapper needs to define a property called wrappedValue.

@propertyWrapper
struct Box {
    var wrappedValue: Int
}

The property wrapper should also implement the access logic for the stored property. Let’s add a getter and a setter, that retrieve and set the value of the private value property:

    private var value = 0

var wrappedValue: Int {
get { value }
set { value = newValue }
}

This property wrapper does nothing meaningful yet. To demonstrate its usage, let’s create a structure Foo:

struct Foo {

Next, declare a property x of type Int. I apply the wrapper to this property by writing the @Box attribute before the property name:

    @Box var x: Int
}

The syntax is short and sweet. Behind the curtain, the compiler generates the code to access the property through the wrapper.

We can create a Foo instance and use it as usual:

var t = Foo()
print(t.x)

// Prints: 0

Next, add some logic to the property wrapper’s code. I modified the getter so that it only returns values greater or equal to 50:

@propertyWrapper
struct Box {
    private var value = 0

var wrappedValue: Int {
get { value > 50 ? value : 50 }
set { value = newValue }
}
}

var t = Foo()
print(t.x)

// Prints: 50

Implementing a Property Wrapper that Base64-Encodes String Properties

Now that I’ve shown you how to create and use a property wrapper let’s implement something useful. The Base64Encoded property wrapper converts the string it wraps to its Base64-encoded representation. 

The setter assigns the new value to the private value property. The getter creates a Data instance from the string’s UTF8 representation. Then, it performs the Base64-encoding by calling the base64EncodedString() Data instance method.

@propertyWrapper
struct Base64Encoded {

private var value = “”

var wrappedValue: String {
get { Data(value.utf8).base64EncodedString() }
set { value = newValue }
}
}

Create a new structure called Payload and apply the wrapper to the text property. 

struct Payload {
    @Base64Encoded var text: String
}

var p = Payload()
p.text = “Property wrappers are awesome!”
print(p.text)

There’s nothing unusual in the way we access the Payload object’s text instance. However, the property gets set and retrieved through the Base64Encoded property wrapper. The output shows the Base64-encoded version of the “Property wrappers are awesome!” string:

UHJvcGVydHkgd3JhcHBlcnMgYXJlIGF3ZXNvbWUh

You can validate the output using online tools such as https://www.base64encoder.io.

Head over to my GitHub repository to download the complete source code: https://github.com/nyisztor/swift-features/blob/master/PropertyWrappers.swift.

Property Wrappers — proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md.

Summary

Property wrappers can reduce the complexity of our code tremendously – especially if we use a lot of boilerplate, repetitive code to access specific properties. Having all the logic in its dedicated entity allows for a cleaner, shorter, and more elegant code.

I hope you’ve got a taste of what Swift property wrappers can do for us. It’s an excellent addition that opens up a plethora of possibilities.