Bird
Raised Fist0
Swiftprogramming~20 mins

Composing property wrappers in Swift - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Swift Property Wrapper Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of nested property wrappers

What is the output of the following Swift code using two composed property wrappers?

Swift
import Foundation

@propertyWrapper
struct Trimmed {
    private var value: String = ""
    var wrappedValue: String {
        get { value }
        set { value = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
    }
    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue
    }
}

@propertyWrapper
struct Uppercased {
    private var value: String = ""
    var wrappedValue: String {
        get { value }
        set { value = newValue.uppercased() }
    }
    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue
    }
}

struct User {
    @Trimmed @Uppercased var name: String
}

var user = User(name: "  swift  ")
print(user.name)
A"SWIFT"
B" SWIFT "
C"swift"
D"Swift"
Attempts:
2 left
💡 Hint

Remember the order in which property wrappers are applied matters.

❓ Predict Output
intermediate
2:00remaining
Value of composed property wrappers with initial values

What will be the value of settings.title after this code runs?

Swift
@propertyWrapper
struct Capitalized {
    private var value: String = ""
    var wrappedValue: String {
        get { value }
        set { value = newValue.capitalized }
    }
    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue
    }
}

@propertyWrapper
struct Suffix {
    private var value: String = ""
    private let suffix: String
    var wrappedValue: String {
        get { value }
        set { value = newValue + suffix }
    }
    init(wrappedValue: String, suffix: String) {
        self.suffix = suffix
        self.wrappedValue = wrappedValue
    }
}

struct Settings {
    @Suffix(suffix: "!") @Capitalized var title: String
}

var settings = Settings(title: "hello world")
print(settings.title)
A"Hello World!"
B"hello world!"
C"HELLO WORLD!"
D"Hello world!"
Attempts:
2 left
💡 Hint

Check the order of wrappers and how each modifies the string.

🔧 Debug
advanced
2:00remaining
Identify the error in composing property wrappers

What error does this Swift code produce when compiling?

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

@propertyWrapper
struct Increment {
    var wrappedValue: Int {
        get { value }
        set { value = newValue + 1 }
    }
    private var value: Int = 0
    init(wrappedValue: Int) {
        self.wrappedValue = wrappedValue
    }
}

struct Counter {
    @DoubleValue @Increment var count: Int
}

let c = Counter(count: 3)
AError: Missing initializer for property 'value' in Increment
BError: Recursive setter call causing infinite loop
CError: Cannot apply two property wrappers to the same property
DNo error, compiles successfully
Attempts:
2 left
💡 Hint

Look at the setter of DoubleValue and what happens when it sets wrappedValue.

📝 Syntax
advanced
2:00remaining
Which option correctly composes property wrappers with parameters?

Which of the following Swift code snippets correctly composes two property wrappers where one has a parameter?

A@Trimmed(suffix: "!") @Suffix var text: String = " hello "
B@Trimmed @Suffix(suffix: "!") var text: String = " hello "
C@Suffix @Trimmed(suffix: "!") var text: String = " hello "
D@Suffix(suffix: "!") @Trimmed var text: String = " hello "
Attempts:
2 left
💡 Hint

Remember how to apply parameters to property wrappers and their order.

🚀 Application
expert
3:00remaining
Number of times wrappedValue setter is called in composed wrappers

Given these two property wrappers and their composition, how many times is the wrappedValue setter called when setting example.value = 5?

Swift
@propertyWrapper
struct Logger {
    var wrappedValue: Int {
        didSet { print("Logger set to \(wrappedValue)") }
    }
    init(wrappedValue: Int) {
        self.wrappedValue = wrappedValue
    }
}

@propertyWrapper
struct Doubler {
    var wrappedValue: Int {
        get { value }
        set {
            value = newValue * 2
            print("Doubler set to \(value)")
        }
    }
    private var value: Int
    init(wrappedValue: Int) {
        self.value = wrappedValue * 2
        print("Doubler init with \(value)")
    }
}

struct Example {
    @Logger @Doubler var value: Int
}

var example = Example(value: 3)
example.value = 5
A1 time
B3 times
C2 times
D4 times
Attempts:
2 left
💡 Hint

Trace the setter calls from the outer wrapper to the inner wrapper.

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