Bird
Raised Fist0
Swiftprogramming~10 mins

Composing property wrappers in Swift - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Composing property wrappers
Define Wrapper A
↓
Define Wrapper B
↓
Apply Wrapper B on Wrapper A
↓
Use Composed Wrapper on Property
↓
Access Property
↓
Wrapper B logic runs
↓
Wrapper A logic runs
↓
Final value returned
This flow shows how two property wrappers are defined and then combined by applying one wrapper on another, so when the property is accessed, the wrappers run in order.
Execution Sample
Swift
@propertyWrapper
struct WrapperA {
  var wrappedValue: Int
  init(wrappedValue: Int) {
    self.wrappedValue = wrappedValue
  }
}

@propertyWrapper
struct WrapperB {
  var inner: WrapperA
  init(wrappedValue: WrapperA) {
    self.inner = wrappedValue
  }
  var wrappedValue: Int {
    get { inner.wrappedValue }
    set { inner.wrappedValue = newValue }
  }
}

@WrapperB @WrapperA var number = 10
print(number)
This code defines two simple wrappers and composes them on a property, then prints the final value.
Execution Table
StepActionWrapper InvolvedValue BeforeValue AfterNotes
1Initialize WrapperA with 10WrapperAN/A10WrapperA stores 10
2Initialize WrapperB with WrapperA instanceWrapperBN/AWrapperA instanceWrapperB wraps WrapperA
3Access property 'number'WrapperBWrapperA instanceCalls WrapperB.wrappedValue getterWrapperB getter runs first
4WrapperB getter calls WrapperA getterWrapperA1010WrapperA getter returns 10
5WrapperB getter returns value 10WrapperB1010Final value is 10
6Print valueNone1010Output is 10
💡 Property accessed and wrappers executed in order, final value 10 returned
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 3Final
WrapperA.wrappedValueN/A10101010
WrapperB.wrappedValueN/AN/AWrapperA instance1010
numberN/AN/AN/A1010
Key Moments - 3 Insights
Why does WrapperB's getter run before WrapperA's getter when accessing the property?
Because WrapperB is applied outermost, it wraps WrapperA, so accessing the property calls WrapperB's getter first, which then calls WrapperA's getter (see execution_table steps 3 and 4).
What value does WrapperA store initially?
WrapperA stores the initial value 10 directly when initialized (see execution_table step 1).
How does the final printed value relate to the wrappers?
The final printed value is the result after both wrappers' getters run, which is 10 here (see execution_table step 6).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what value does WrapperA hold after initialization (Step 1)?
A10
BWrapperB instance
CN/A
D0
💡 Hint
Check the 'Value After' column in Step 1 of the execution_table.
At which step does WrapperB's getter call WrapperA's getter?
AStep 2
BStep 3
CStep 4
DStep 5
💡 Hint
Look for the step where WrapperA's getter returns a value inside WrapperB's getter (execution_table).
If we reversed the order of wrappers to @WrapperA @WrapperB, which wrapper's getter runs first?
AWrapperB
BWrapperA
CBoth run simultaneously
DNeither runs
💡 Hint
Recall that the outermost wrapper's getter runs first; reversing order changes which is outermost.
Concept Snapshot
@propertyWrapper struct WrapperA { var wrappedValue: Int init(wrappedValue: Int) { self.wrappedValue = wrappedValue } }
@propertyWrapper struct WrapperB { var wrappedValue: Int }
Use @WrapperB @WrapperA var x = 10 to compose wrappers.
Accessing x calls WrapperB's getter, which calls WrapperA's getter.
Wrappers run outer to inner, layering behavior on the property.
Full Transcript
This example shows how to compose two property wrappers in Swift. WrapperA and WrapperB are defined as simple wrappers holding an Int. When we apply @WrapperB @WrapperA to a property, WrapperB wraps WrapperA. Accessing the property calls WrapperB's getter first, which then calls WrapperA's getter, returning the stored value 10. The execution table traces each step: initializing wrappers, accessing the property, and printing the final value. The variable tracker shows how values change or stay the same through the steps. Key moments clarify why the outer wrapper runs first and how values flow. The quiz tests understanding of wrapper order and value flow. This helps beginners see how composing wrappers layers behavior on properties in Swift.

Practice

(1/5)
1. What does it mean to compose property wrappers in Swift?
easy
A. Apply property wrappers only to functions
B. Use only one property wrapper per property
C. Create a new property wrapper by subclassing another
D. Stack multiple property wrappers on a single property to combine behaviors

Solution

  1. Step 1: Understand property wrappers

    Property wrappers add behavior to properties in Swift.
  2. Step 2: Define composition meaning

    Composing means stacking multiple wrappers on one property to combine their effects.
  3. Final Answer:

    Stack multiple property wrappers on a single property to combine behaviors -> Option D
  4. Quick Check:

    Composing = stacking wrappers [OK]
Hint: Remember: composing means stacking wrappers on one property [OK]
Common Mistakes:
  • Thinking only one wrapper can be used per property
  • Confusing subclassing with composing
  • Applying wrappers to functions instead of properties
2. Which of the following is the correct syntax to compose two property wrappers @WrapperA and @WrapperB on a property var value: Int such that @WrapperA is applied first (innermost)?
easy
A. @WrapperB @WrapperA var value: Int
B. @WrapperA @WrapperB var value: Int
C. var @WrapperA @WrapperB value: Int
D. var value: Int @WrapperA @WrapperB

Solution

  1. Step 1: Recall property wrapper order

    Property wrappers apply from right to left, so the rightmost is applied first.
  2. Step 2: Check syntax order

    Correct syntax places wrappers before the property, so @WrapperB @WrapperA var value: Int applies @WrapperA first, then @WrapperB.
  3. Final Answer:

    @WrapperB @WrapperA var value: Int -> Option A
  4. Quick Check:

    Right to left wrapper order = @WrapperB @WrapperA var value: Int [OK]
Hint: Remember wrappers apply right to left, so last wrapper is closest to var [OK]
Common Mistakes:
  • Placing wrappers after the variable name
  • Reversing the order of wrappers
  • Using wrappers inside the variable declaration
3. Given these property wrappers:
 @propertyWrapper
 struct WrapperA {
   var wrappedValue: Int
   init(wrappedValue: Int) { self.wrappedValue = wrappedValue + 1 }
 }

 @propertyWrapper
 struct WrapperB {
   var wrappedValue: Int
   init(wrappedValue: Int) { self.wrappedValue = wrappedValue * 2 }
 }

 struct Example {
   @WrapperA @WrapperB var value: Int = 3
 }

What is the value of Example().value?
medium
A. 7
B. 8
C. 6
D. 10

Solution

  1. Step 1: Apply wrappers right to left

    First, @WrapperB applies: 3 * 2 = 6.
  2. Step 2: Apply @WrapperA next

    Then @WrapperA adds 1: 6 + 1 = 7.
  3. Final Answer:

    7 -> Option A
  4. Quick Check:

    (3 * 2) + 1 = 7 [OK]
Hint: Apply wrappers from right to left to find final value [OK]
Common Mistakes:
  • Applying wrappers left to right
  • Forgetting to add 1 in WrapperA
  • Multiplying after adding instead of before
4. Consider this code snippet:
 @propertyWrapper
 struct WrapperX {
   var wrappedValue: Int
   init(wrappedValue: Int) { self.wrappedValue = wrappedValue + 5 }
 }

 struct Test {
   @WrapperX @WrapperX var number: Int = 10
 }

What is the error in this code?
medium
A. Cannot apply the same property wrapper twice on one property
B. The property wrapper's init is called twice, causing unexpected behavior
C. No error; code compiles and runs correctly
D. The property wrapper must have a default initializer

Solution

  1. Step 1: Check if multiple same wrappers allowed

    Swift allows stacking the same property wrapper multiple times.
  2. Step 2: Analyze wrapper initialization

    Each wrapper adds 5, so first adds 5 to 10 = 15, second adds 5 to 15 = 20.
  3. Final Answer:

    No error; code compiles and runs correctly -> Option C
  4. Quick Check:

    Same wrapper stacking allowed = No error; code compiles and runs correctly [OK]
Hint: Same wrapper can be stacked; no syntax error [OK]
Common Mistakes:
  • Assuming duplicate wrappers cause errors
  • Expecting default initializer requirement
  • Confusing runtime behavior with compile errors
5. You want to create a property that is both clamped between 0 and 100 and logged when changed. You have two property wrappers:
 @propertyWrapper
 struct Clamped {
   private var value: Int
   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)
   }
 }

 @propertyWrapper
 struct Logged {
   private var value: Int
   var wrappedValue: Int {
     get { value }
     set {
       print("Value changed to \(newValue)")
       value = newValue
     }
   }
   init(wrappedValue: Int) {
     self.value = wrappedValue
   }
 }

 struct Settings {
   @Logged @Clamped(0...100) var score: Int = 150
 }

What will be printed and what is the final value of Settings().score?
hard
A. Prints 'Value changed to 150', final value 150
B. Prints nothing, final value 100
C. Prints 'Value changed to 100', final value 100
D. Prints 'Value changed to 0', final value 0

Solution

  1. Step 1: Apply wrappers right to left

    First, @Clamped(0...100) clamps 150 to 100 in init.
  2. Step 2: Then @Logged receives 100

    @Logged init sets value=100 directly (no setter called, no print).
  3. Final Answer:

    Prints nothing, final value 100 -> Option B
  4. Quick Check:

    Clamp then direct init set = no print, value 100 [OK]
Hint: Initial values chain through inits right to left; no setter/print on init [OK]
Common Mistakes:
  • Thinking log prints during initialization
  • Thinking clamp applies after log
  • Assuming propagation calls inner setters
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard