Understanding Property Wrapper

Manoj Aher
4 min readJun 5, 2020

--

Property wrapper adds a wrapper over a property which stores it and defines how the property will behave

As the name suggests its a wrapper over the property, so you can fiddle with the raw value before returning it. Property wrappers can be used with struct enum and class.

You must have seen and even used @State, @Binding, @Published, @ObservedObject and a lot more in SwiftUI which highly relies on Property Wrapper.

We will implement a Music Rating app where a user can rate the music from 1 to 5. If a user mistakenly sets the value greater than 5 (which means he really liked the music) we reset the value to 5 which is the highest rating. Similarly, if he disliked the music and set the value to 0, we reset the value to 1 which is the lowest possible rating.

Image by Gerhard Gellinger from Pixabay

Defining a property wrapper:

  1. Prefix the keyword @properyWrapper before the struct, enum, or class. We have created a struct Rating and prefixed @properyWrapper before struct Rating.
  2. Property wrapper must contain a non-static property named wrappedValue. You can use the getter and setter methods to perform your checks and validations for the variables.
https://gist.github.com/manojaher/29e589025c18bf0fb83b419e9044acec

Usage:

  1. To use the property wrapper, you prefix the wrapper’s name before the property as an attribute. We have prefixed @Rating that goes before the attribute rating.
  2. To use the variable just set the attribute value. If you set the value, the wrappedValue setter gets called where validation is performed. If the newValue is higher than 5, the rating is reset to 5. Similarly, when the user sets the value smaller than 1, it resets to 1.

Simple enough! Let’s take a more practical example.

Setting Initial Values on Wrapped Properties

Hardcoding the maximum and minimum ratings is not the right way to do it. So we will be passing the max and min ratings to the initializer. As you can see in the below code, we have added multiple initializers.

https://gist.github.com/manojaher/5063fee4ccfb70c5503c43d76499fea5

Let’s understand how initializers are called on PropertyWrappers.

  1. When you don’t specify an initial value for a property init() is called where we set the max, min, and default rating.
// calls init()
@Rating var masakali: Int

2. When you specify an initial value for a property init(wrappedValue:) is called. You can set the wrapped value in two ways. The first one by assigning value to it. The second way is by adding arguments after they attribute.

When you write parameters in the parentheses after the attribute you basically call the initializer which accepts those arguments.

struct MusicRating {
// calls init(wrappedValue:)
@Rating var masakali: Int = 5
@Rating (wrappedValue: 5) var masakali: Int
}

3. On similar principles, we can have more than one argument in initializers. When you write parameters in the parentheses after attribute init(wrappedValue: maxRating: minRating:)gets called.

struct MusicRating {
// calls init(wrappedValue: maxRating: minRating:)
@Rating (maxRating: 5, minRating: 1) var masakali: Int = 5
@Rating (wrappedValue: 0, maxRating: 5, minRating: 1) var masakali: Int
}

Projected value in a property wrapper

You can add additional functionality on property wrapper using projected values. The name of the projected value will be similar to wrapped value and can be accessed by appending a $ sign before the wrapped value.

Projected values are optional to implement and could be used if you add some extra information along with the wrapped value. In the below implementation, the projected value returns the number of stars on the rating given by the user.

https://gist.github.com/manojaher/6e46b78ec721a68af9764aafb044fe91

Using UserDefaults with property wrapper

UserPreferences is a property wrapper that helps to save and get values from UserDefaults.

https://gist.github.com/manojaher/cf5c2bca02856e67e86bd8e55c3f2f4e

Using SecureDefaults to store Secure object

SecureDefaults can be used to wrap the objects conforming to SecureCoding into and from UserDefaults.

https://gist.github.com/manojaher/8658bf913c83562af2dc10257b81c68e

That’s pretty much what propertyWrapper is all about. One of the features I will be using extensively in my projects and will be updating the same blog. do you have a use case that you think should be mentioned here? Let me know in the comments!

Read more about Property Wrappers here

--

--