WrappedValue and projectedValue help you control how a property behaves and what extra information it can provide.
WrappedValue and projectedValue in Swift
@propertyWrapper struct WrapperName { var wrappedValue: Type var projectedValue: ExtraType init(wrappedValue: Type) { self.wrappedValue = wrappedValue self.projectedValue = ... // set extra info } }
wrappedValue is the main value the property holds.
projectedValue is extra info you can access with a $ prefix.
@propertyWrapper struct Capitalized { private var value: String = "" var wrappedValue: String { get { value } set { value = newValue.capitalized } } init(wrappedValue: String) { self.wrappedValue = wrappedValue } }
@propertyWrapper struct Logged { var wrappedValue: Int { didSet { print("Value changed to \(wrappedValue)") } } init(wrappedValue: Int) { self.wrappedValue = wrappedValue } }
projectedValue.@propertyWrapper struct Toggle { var wrappedValue: Bool var projectedValue: String { wrappedValue ? "On" : "Off" } init(wrappedValue: Bool) { self.wrappedValue = wrappedValue } }
This program uses a property wrapper Trimmed that removes spaces around a string. The projectedValue gives the length of the trimmed string. We create a user with spaces around the name, then print the trimmed name and its length.
import Foundation @propertyWrapper struct Trimmed { private var value: String = "" var wrappedValue: String { get { value } set { value = newValue.trimmingCharacters(in: .whitespacesAndNewlines) } } var projectedValue: Int { value.count } init(wrappedValue: String) { self.wrappedValue = wrappedValue } } struct User { @Trimmed var name: String } var user = User(name: " Alice ") print("Name: '\(user.name)'" ) print("Length: \(user.$name)")
You access wrappedValue normally, but projectedValue with a $ before the property name.
Property wrappers make your code cleaner by reusing common property logic.
Not all property wrappers need a projectedValue, but it is useful for extra info.
wrappedValue is the main value stored or controlled by the property wrapper.
projectedValue is extra information or behavior you can access with $property.
Use these to add helpful features to your properties without repeating code.
Practice
wrappedValue represent in a Swift property wrapper?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 AQuick Check:
wrappedValue = main stored value [OK]
- Confusing wrappedValue with projectedValue
- Thinking wrappedValue is a method
- Assuming wrappedValue holds extra metadata
projectedValue of a property wrapper named score?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 BQuick Check:
projectedValue = $propertyName [OK]
- Trying to access projectedValue as a normal property
- Using dot syntax incorrectly
- Confusing $score with score.$projectedValue
@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)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.Final Answer:
John Doe\nLength: 8 -> Option AQuick Check:
wrappedValue capitalizes, projectedValue shows length [OK]
- Counting characters without space
- Ignoring capitalization effect
- Using p.name instead of p.$name for projectedValue
@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)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 CQuick Check:
wrappedValue needs initial value or storage [OK]
- Trying to mutate wrappedValue inside didSet
- Assuming didSet works without storage
- Confusing struct vs class requirement
wrappedValue and projectedValue to achieve this?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 DQuick Check:
wrappedValue = main data, projectedValue = extra info [OK]
- Swapping roles of wrappedValue and projectedValue
- Trying to store multiple values in wrappedValue
- Using projectedValue as main storage
Ready to prove it?
Pass the test and this pattern moves unknown
