Understanding Property Wrappers Swift
Property Wrappers
Property wrappers in swift help us to separate the code that manages the validation and the code that actually defines it.
Code that defines the property
@UserIdentifier var userId: Int
@UserIdentifier is a custom way to manage the storage. Don't worry it will be more clear in some time, but my whole point was to clear the understanding on the difference between defining and managing a property (with the help of Property Wrapper).
Consider a use case of UserIdentifier:
- We want to have a userId which can take maximum up to 100 ids.
- If a user tries to set it to a value more than 100, it won't allow
- Provide a validation flag if value exceeds then 100. i.e true if any adjustments made or else false.
Think of this validation to be added at 5 different properties of different class. It would be very difficult to manage , may be write extension to handle this.
extension Int {
func validateMax() -> Int {
if self > 100 {
return 100
}
return self
}
}
Probably not the best way. Also it does not tell us the property was modified or not.
Let's try with a different approach , using Property Wrapper. Here we write the management code once and apply it to multiple properties.
Writing the management code will be bit extensive but using it will be a piece of cake ( by using just the attribute @UserIdentifier)
import Foundation
@propertyWrapper
struct UserIdentifier {
private var userId: Int
/// Second functionality of Property Wrapper - Projected Value
var projectedValue: Bool
init() {
projectedValue = false
userId = 0
}
/// First functionality of Property wrapper - Wrapped Value
var wrappedValue: Int {
get {
return userId
}
set {
if newValue > 100 {
userId = 100
projectedValue = true
} else {
userId = newValue
projectedValue = false
}
}
}
}
struct UserDetails {
@UserIdentifier var userId: Int
}
var userDetails = UserDetails()
userDetails.userId = 2
print("Projected Value => \(userDetails.$userId)")
print("Wrapped Value => \(userDetails.userId)")
What is Wrapper Name ?
How to apply Property Wrapper to a Property?
We user the property Wrapper name i.e "UserIdentifier" before a property as an attribute
(@) => attribute
(wrapper name) => UserIdentifier
var userId: Int => property name
Combining all of them together , we apply Property Wrapper to a property.
@UserIdentifier var userId: Int
Wrapped Value
UserIdentifier structure makes sure's the number it wraps always has number less than or equal to 100.
Any attempt to set a value more than 100, will limit to 100.
How to access wrapped Value?
So if the structure "UserDetails" uses property wrapper for "userId" , we access it like "userDetails.userId"
Projected Value
Projected value can be of any type , in case of above example we are using it as Bool.
The projected value provides additional details of an instance in case any value being set is out of the range i.e more than 100 or less than 100 in the above case.
How to access projected Value?
In the example above it will print false , when we try to set the value of "userId" to 2.
If we try to set value for example 102. It will print true.
userDetails.userId = 102
It will print true for projected value.
userDetails.$userId
Comments
Post a Comment