The @propertyWrapper lets you create a reusable way to add extra behavior to variables. It helps keep your code clean and organized.
@propertyWrapper declaration in Swift
@propertyWrapper struct WrapperName { private var value: Type var wrappedValue: Type { get { value } set { value = newValue } } init(wrappedValue initialValue: Type) { self.value = initialValue } }
The wrappedValue property is required. It controls how the variable behaves.
The init(wrappedValue:) lets you set a default value when using the wrapper.
@propertyWrapper struct Capitalized { private var value: String = "" var wrappedValue: String { get { value } set { value = newValue.capitalized } } init(wrappedValue: String) { self.value = wrappedValue.capitalized } }
@propertyWrapper struct Clamped { private var value: Int private let range: ClosedRange<Int> var wrappedValue: Int { get { value } set { value = min(max(newValue, range.lowerBound), range.upperBound) } } init(wrappedValue: Int, _ range: ClosedRange<Int>) { self.range = range self.value = min(max(wrappedValue, range.lowerBound), range.upperBound) } }
This program shows how the @Capitalized property wrapper automatically capitalizes the name when setting it.
import Foundation @propertyWrapper struct Capitalized { private var value: String = "" var wrappedValue: String { get { value } set { value = newValue.capitalized } } init(wrappedValue: String) { self.value = wrappedValue.capitalized } } struct Person { @Capitalized var name: String } var person = Person(name: "john doe") print(person.name) // Prints "John Doe" person.name = "jane smith" print(person.name) // Prints "Jane Smith"
You can add extra properties or methods inside your property wrapper to support more features.
Property wrappers can be used on variables in structs, classes, and enums.
Remember to use @propertyWrapper before your wrapper struct or class.
@propertyWrapper helps add reusable behavior to variables.
It requires a wrappedValue property to control the variable.
You use it by adding @YourWrapperName before a variable.
Practice
@propertyWrapper in Swift?Solution
Step 1: Understand what @propertyWrapper does
@propertyWrapper is used to add reusable behavior to variables, such as validation or transformation, by controlling how their values are stored and accessed.Step 2: Compare with other options
Options B, C, and D describe unrelated Swift features: defining types, async functions, and error handling, which are not the purpose of @propertyWrapper.Final Answer:
To add reusable behavior to variables by controlling their access and storage -> Option CQuick Check:
@propertyWrapper purpose = reusable variable behavior [OK]
- Confusing @propertyWrapper with class or struct definitions
- Thinking it handles async code or errors
- Believing it creates new data types
Capitalized?Solution
Step 1: Recall the syntax for declaring a property wrapper
A property wrapper must be declared as a struct or class with the@propertyWrapperattribute before its definition, and it must have awrappedValueproperty.Step 2: Analyze each option
struct Capitalized { var wrappedValue: String } misses the@propertyWrapperattribute. @propertyWrapper struct Capitalized { var wrappedValue: String } correctly uses@propertyWrapperbefore the struct and defineswrappedValue. struct Capitalized { @propertyWrapper var wrappedValue: String } incorrectly places@propertyWrapperbefore the property, which is invalid. @propertyWrapper var Capitalized: String tries to declare a variable with@propertyWrapper, which is incorrect syntax.Final Answer:
@propertyWrapper struct Capitalized { var wrappedValue: String } -> Option AQuick Check:
Property wrapper syntax = @propertyWrapper before struct [OK]
- Placing @propertyWrapper before the property instead of the struct
- Omitting the @propertyWrapper attribute
- Trying to declare property wrapper as a variable
@propertyWrapper
struct Trimmed {
var wrappedValue: String
init(wrappedValue: String) {
self.wrappedValue = wrappedValue.trimmingCharacters(in: .whitespaces)
}
}
struct User {
@Trimmed var name: String
}
let user = User(name: " Alice ")
print(user.name)Solution
Step 1: Understand the property wrapper behavior
TheTrimmedwrapper trims whitespace from the string when initialized in itsinit. So the initial value " Alice " is trimmed to "Alice".Step 2: Check the printed value
Theuser.nameaccesses the wrapped value, which is trimmed. So printinguser.nameoutputs "Alice" without spaces.Final Answer:
"Alice" -> Option AQuick Check:
Trimmed wrapper removes spaces = "Alice" [OK]
- Assuming original spaces remain
- Thinking didSet runs before init
- Overlooking the trimming in init
@propertyWrapper
struct Positive {
var wrappedValue: Int
init(wrappedValue: Int) {
if wrappedValue < 0 {
wrappedValue = 0
}
self.wrappedValue = wrappedValue
}
}Solution
Step 1: Analyze the init parameter usage
In Swift, function parameters are constants and cannot be assigned new values. The linewrappedValue = 0inside the init tries to assign to the parameter, which causes an error.Step 2: Check other options
The @propertyWrapper attribute is present, so B is wrong. The wrappedValue can be stored or computed, so C is wrong. The code has an error, so A is wrong.Final Answer:
Cannot assign to parameter 'wrappedValue' inside init -> Option DQuick Check:
Function parameters are constants = assignment error [OK]
- Trying to assign directly to init parameters
- Thinking wrappedValue must be computed
- Ignoring the @propertyWrapper attribute
Clamped that limits an Int value between a minimum and maximum. Which of the following is the correct way to declare it so that you can use it like @Clamped(min: 0, max: 10) var score: Int?Solution
Step 1: Understand the requirements for Clamped
The wrapper must accept min and max parameters, clamp the wrappedValue between them, and allow usage with@Clamped(min: 0, max: 10).Step 2: Analyze each option
@propertyWrapper struct Clamped { private var value: Int let min: Int let max: Int var wrappedValue: Int { get { value } set { value = min(max(newValue, min), max) } } init(wrappedValue: Int, min: Int, max: Int) { self.min = min self.max = max self.value = min(max(wrappedValue, min), max) } } correctly defines min and max as let constants, stores the value privately, clamps in init and setter, and has the correct init signature. @propertyWrapper struct Clamped { var wrappedValue: Int init(min: Int, max: Int) { wrappedValue = 0 } } lacks wrappedValue initialization and clamping logic. @propertyWrapper struct Clamped { var wrappedValue: Int init(wrappedValue: Int) { wrappedValue = 0 } } does not accept min and max parameters. @propertyWrapper struct Clamped { var wrappedValue: Int { didSet { if wrappedValue < min { wrappedValue = min } if wrappedValue > max { wrappedValue = max } } } let min: Int let max: Int } tries to clamp in didSet but does not initialize wrappedValue properly and does not clamp in init, which can cause invalid initial values.Final Answer:
@propertyWrapper struct Clamped { private var value: Int let min: Int let max: Int var wrappedValue: Int { get { value } set { value = min(max(newValue, min), max) } } init(wrappedValue: Int, min: Int, max: Int) { self.min = min self.max = max self.value = min(max(wrappedValue, min), max) } } -> Option BQuick Check:
Clamped wrapper needs init with min/max and clamping in setter [OK]
- Not accepting min and max in init
- Not clamping value on initialization
- Trying to clamp only in didSet without proper init
Ready to prove it?
Pass the test and this pattern moves unknown
