Property Wrappers In Swift
Swift 5.1 introduced a new feature to the language: the property wrapper.
A property wrapper is a generic data structure that has read/write capabilities, while at the same time providing and enforcing additional functionalities.
If this bookish definition looks hard you can think of Property Wrappers as Wrapping a property to give it some extra functionality.
PROPERTY WRAPPER REQUIREMENTS
a property wrapper must adhere to certain requirements to be valid. Here are the key requirements for creating a property wrapper:
@propertyWrapper
Attribute:
- The property wrapper must be annotated with the
@propertyWrapper
attribute. This signals to the compiler that the structure or class is intended to be used as a property wrapper. - The property wrapper must have a property named
wrappedValue
. This property is used to store the actual value of the property being wrapped.
@propertyWrapper
struct MyPropertyWrapper {
// Define the wrappedValue property that will store the actual value
var wrappedValue: Int
// You can include additional logic here, such as validation or transformation
init(wrappedValue: Int) {
// Additional logic if needed
self.wrappedValue = wrappedValue
}
}
CUSTOM WRAPPER
SCENARIO: Suppose you want to store a username field in your app to process registering a user but there is a criteria that you need to have the username in lowercase. Instead of checking this rule every time a username is stored, it would be easier if this rule could be enforced programmatically. This is where the property wrapper comes in real handy.
@propertyWrapper
struct Lowercased {
private(set) var value: String = ""
var wrappedValue: String {
get { value }
set { value = newValue.lowercased() }
}
init(wrappedValue: String) {
self.value = wrappedValue.lowercased()
}
}
Explanation:
- The
Lowercased
struct is annotated with@propertyWrapper
. - It has private property
value
to store the lowercase string. - The
wrappedValue
property is where the actual logic is implemented. When getting the value, it returns the stored value; when setting the value, it sets the lowercase version of the input string. - The
init
method initializes thevalue
property with the lowercase version of the provided string.
Now, let’s see an example of using this property wrapper:
struct User {
@LowerCased var userName: String // property wrappers cannot be a let
var email: String
}
In this example, the @Lowercased
property wrapper is applied to the username
property of the User
struct. When you assign a value to username
, the property wrapper automatically lowercase the input string. This allows you to ensure that the stored string is always in lowercase without explicitly calling the lowercased()
method each time you set the value.
You can see below that the username is converted to lowercase.
Understanding Dollar Sign $
and Underscore _ in a property wrapper:
Swift will “synthesize” (autogenerate) your new property wrapper with 2 new properties behind the scenes and these are
1- Underscore _ :
We can access the wrapper type by adding an underscore to the variable name
Here _username
is an instance of Lowercased
we can access all the public properties and functions of the Lowercased
property wrapper
you can see using the _userName
the public properties SwiftUI exposes for the @published property wrapper.
2- Dollar Sign $
$ refers to the projected value used in your property wrapper so if you have a property named projectedValue
you can use the $ syntax to access that as shown below. you can expose more api’s through the projected value of your property wrapper .
A property wrapper can return a value of any type as its projected value.
you can see that projectedValue
property for the @published property wrapper is a publisher which you can also access using the $.
Apple’s new framework SwiftUI makes heavy use of property wrappers. so it’s important to understand how they work to understand SwiftUI more.
you can find the code below in the repo