Using WrappedValue and projectedValue in Swift Property Wrappers
📖 Scenario: Imagine you are building a simple app that tracks the progress of tasks. You want to create a custom property wrapper that stores a task's progress as a percentage and also provides a message about the progress.
🎯 Goal: Build a Swift program that uses a property wrapper with wrappedValue to store the progress percentage and projectedValue to provide a progress message.
📋 What You'll Learn
Create a property wrapper named ProgressTracker with wrappedValue and projectedValue
Use wrappedValue to store an integer progress percentage
Use projectedValue to return a string message about the progress
Create a struct Task with a property progress using the ProgressTracker wrapper
Print the progress percentage and the progress message
💡 Why This Matters
🌍 Real World
Property wrappers help you add reusable behavior to properties, such as validation, formatting, or extra info, which is common in app development.
💼 Career
Understanding property wrappers and their wrapped and projected values is important for Swift developers working on iOS or macOS apps to write clean and reusable code.
Progress0 / 4 steps
1
Create the ProgressTracker property wrapper
Create a property wrapper named ProgressTracker with a wrappedValue property of type Int initialized to 0.
Swift
Hint
Use @propertyWrapper before the struct. Define wrappedValue as an Int with default 0.
2
Add projectedValue to provide a progress message
Inside ProgressTracker, add a computed property projectedValue of type String that returns "Progress is X%" where X is the current wrappedValue.
Swift
Hint
Define projectedValue as a computed property returning a string with the current wrappedValue.
3
Create Task struct using ProgressTracker
Create a struct named Task with a property progress that uses the @ProgressTracker property wrapper.
Swift
Hint
Define struct Task with a property progress using @ProgressTracker.
4
Set progress and print wrappedValue and projectedValue
Create an instance of Task named myTask. Set myTask.progress to 75. Then print myTask.progress and myTask.$progress.
Swift
Hint
Create myTask, assign 75 to progress, then print myTask.progress and myTask.$progress.
Practice
(1/5)
1. What does wrappedValue represent in a Swift property wrapper?
easy
A. The main value stored or controlled by the property wrapper
B. An extra method to modify the property
C. A way to access the property's type information
D. A function to reset the property to default
Solution
Step 1: Understand the role of wrappedValue
The wrappedValue is the core value that the property wrapper manages or stores internally.
Step 2: Differentiate from other features
Unlike projectedValue, wrappedValue is the actual data, not extra info or behavior.
Final Answer:
The main value stored or controlled by the property wrapper -> Option A
Quick Check:
wrappedValue = main stored value [OK]
Hint: wrappedValue is the property's actual stored value [OK]
Common Mistakes:
Confusing wrappedValue with projectedValue
Thinking wrappedValue is a method
Assuming wrappedValue holds extra metadata
2. Which syntax correctly accesses the projectedValue of a property wrapper named score?
easy
A. score.projectedValue
B. $score
C. score.$projectedValue
D. score->projectedValue
Solution
Step 1: Recall how to access projectedValue
In Swift, the projectedValue is accessed using the dollar sign prefix before the property name.
Step 2: Match syntax to property name
For a property named score, the projectedValue is accessed as $score.
Final Answer:
$score -> Option B
Quick Check:
projectedValue = $propertyName [OK]
Hint: Use $ before property name to get projectedValue [OK]
Common Mistakes:
Trying to access projectedValue as a normal property
Using dot syntax incorrectly
Confusing $score with score.$projectedValue
3. Given this code, what will be printed?
@propertyWrapper
struct Capitalized {
private var value: String = ""
var wrappedValue: String {
get { value }
set { value = newValue.capitalized }
}
var projectedValue: String {
"Length: \(value.count)"
}
}
struct Person {
@Capitalized var name: String
}
var p = Person()
p.name = "john doe"
print(p.name)
print(p.$name)
medium
A. John Doe
Length: 8
B. john doe
Length: 8
C. John Doe
Length: 7
D. john doe
Length: 7
Solution
Step 1: Understand wrappedValue behavior
Setting p.name to "john doe" triggers the setter, which capitalizes the string to "John Doe".
Step 2: Calculate projectedValue output
The projectedValue returns the length of the capitalized string. "John Doe" has 8 characters including the space.
Hint: wrappedValue changes value, projectedValue gives extra info [OK]
Common Mistakes:
Counting characters without space
Ignoring capitalization effect
Using p.name instead of p.$name for projectedValue
4. Identify the error in this property wrapper usage:
@propertyWrapper
struct Trimmed {
var wrappedValue: String {
didSet { wrappedValue = wrappedValue.trimmingCharacters(in: .whitespaces) }
}
}
struct User {
@Trimmed var username: String
}
var u = User()
u.username = " alice "
print(u.username)
medium
A. wrappedValue cannot be mutated inside didSet
B. Cannot use didSet in property wrapper
C. Missing initial value for wrappedValue
D. Property wrapper must be a class, not struct
Solution
Step 1: Check wrappedValue declaration
The wrappedValue property lacks an initial value or backing storage, causing a compile error.
Step 2: Understand property wrapper requirements
Property wrappers must have a stored wrappedValue or initializer to set it; here it's missing.
Final Answer:
Missing initial value for wrappedValue -> Option C
Quick Check:
wrappedValue needs initial value or storage [OK]
Hint: wrappedValue must have storage or initializer [OK]
Common Mistakes:
Trying to mutate wrappedValue inside didSet
Assuming didSet works without storage
Confusing struct vs class requirement
5. You want to create a property wrapper that stores an integer and also tracks how many times the value was changed. Which approach correctly uses wrappedValue and projectedValue to achieve this?
hard
A. Use projectedValue only to store and access the integer
B. Use projectedValue to store the integer and wrappedValue to return the change count
C. Use wrappedValue for both storing integer and change count
D. Use wrappedValue to store the integer and projectedValue to return the change count
Solution
Step 1: Define roles of wrappedValue and projectedValue
wrappedValue should hold the main integer value; projectedValue can provide extra info like change count.
Step 2: Match roles to requirements
Tracking changes is extra info, so projectedValue is ideal to expose the count without mixing with main value.
Final Answer:
Use wrappedValue to store the integer and projectedValue to return the change count -> Option D
Quick Check:
wrappedValue = main data, projectedValue = extra info [OK]
Hint: wrappedValue stores data, projectedValue tracks extra info [OK]
Common Mistakes:
Swapping roles of wrappedValue and projectedValue
Trying to store multiple values in wrappedValue
Using projectedValue as main storage
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.