Understanding Swift’s Property Wrappers

Don’t be so lazy

Image for post
Image for post
Photo by Jf Brou on Unsplash

Difficulty: Beginner | Easy | Normal | Challenging
This article has been developed using Xcode 11.4.1, and Swift 5.2.2

Prerequisites:

Terminology

lazy variables: A technique in that a property is only created when it is needed

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

Why use property wrappers?

Using Lazy in Swift is useful as it defers initialization of a value until its first access. This is equivalent functionality to wrapping a value in a computed get — lazy makes your code more elegant, easy to read and of course maintainable.

Here is an example of the lazy instantiation of a struct (if you follow along with the Playground, make sure you comment out one of the People instances at a time or the compiler will tell you that you have an invalid declaration of 'People')

Image for post
Image for post
Click for Gist

Effectively for each property on the struct you'd need to have one of these sets of getters and setters. What if you could use a repeatable peice of code that would allow you to be able to reuse code.

Using property wrappers

The idea here is that we can reuse the Wrapper for as many properties as we would like on the People struct. This gives the following code:

Image for post
Image for post
Click for Gist

Effectively we are abstracting the @propertyWrapper away from our struct or class instances. The Wrapper provides transparency since when we are using the Wrapper using generics we are simply using an Array of String.

It is really common to use ISO8601DateFormatter to provide a standardized way of presenting Data and Time. Since this can be reused in many struct and class instances, this is certainly is great use of Swift's Property Wrappers.

Image for post
Image for post
Click for Gist

Where of course in the user.createdAt is the date, and print(user.createdAt) are in fact the same date, but the second is formatted for the screen.

projectedValue

We can go as far as to look at our two createdAt properties on our user instance: user.createdAt and user.$createdAt

Each of the two examples above gives us two different outputs — since the second of the two is a projectedValue.

So the $ indicates that we want to access the property wrapper itself rather than the property that it is wrapping.

type(of: user.createdAt) // Foundation.Date.Type 
type(of: user.$createdAt) // String.Type

Now of course to use projectedValue we need to have a var projectedValue property in our propertyWrapper — which is of course true in our example code as set out (which represents a user).

This means that user.createdAt is a simple date, but user.$createdAt is a nicely formatted date in this example.

Awesome!

Conclusion

Property wrappers are a Swift feature that can help you write easy to read and maintainable code in Swift. They have been available since Swift 5.1, and have particular power when coupled with SwiftUI — so this is certainly something you should look at as you enhance your understanding of Swift and iOS/iPadOS.

When creating code you should always think about reusability, what a great use of abstraction in the constructs of the language!

The code from this is included in the attached Repo.

If you’ve any questions, comments or suggestions please hit me up on Twitter

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store