📖 Scenario: Imagine you are building a simple app that tracks user settings. You want to make sure some settings have default values and can be easily configured.
🎯 Goal: You will create a property wrapper that allows setting a default value and then use it to manage user settings with configurable defaults.
📋 What You'll Learn
Create a property wrapper called DefaultValue that stores a wrapped value.
Add a configuration property called defaultValue to the wrapper.
Use the property wrapper on a struct's properties with different default values.
Print the values of the properties to see the defaults in action.
💡 Why This Matters
🌍 Real World
Property wrappers help manage default values and add behavior to properties in apps, making code cleaner and easier to maintain.
💼 Career
Understanding property wrappers is useful for Swift developers working on iOS or macOS apps to write reusable and configurable code.
Progress0 / 4 steps
1
Create the property wrapper with a default value
Create a property wrapper called DefaultValue that has a generic type Value. Inside it, declare a variable wrappedValue of type Value. Add an initializer that accepts a parameter called defaultValue of type Value and sets wrappedValue to this defaultValue.
Swift
Hint
Use @propertyWrapper before the struct. The initializer should set wrappedValue to the defaultValue parameter.
2
Create a struct with properties using the wrapper
Create a struct called UserSettings. Inside it, declare two properties: username and isDarkMode. Use the @DefaultValue property wrapper on both. Set the default value for username to "Guest" and for isDarkMode to false.
Swift
Hint
Use the property wrapper syntax @DefaultValue(defaultValue: ...) before each property.
3
Create an instance and access the properties
Create a variable called settings and assign it a new instance of UserSettings. Then, access the properties username and isDarkMode from settings.
Swift
Hint
Create settings as UserSettings(). Access properties with dot notation like settings.username.
4
Print the property values
Print the values of settings.username and settings.isDarkMode using two separate print statements.
Swift
Hint
Use print(settings.username) and print(settings.isDarkMode) to show the values.
Practice
(1/5)
1. What is the main purpose of using property wrappers with configuration in Swift?
easy
A. To automatically generate UI elements
B. To create new data types from scratch
C. To replace functions with variables
D. To add reusable behavior to properties with customizable settings
Solution
Step 1: Understand property wrappers
Property wrappers add extra behavior to properties, like validation or formatting.
Step 2: Understand configuration
Configuration lets you customize how the wrapper behaves for each property.
Final Answer:
To add reusable behavior to properties with customizable settings -> Option D
Hint: Look for @propertyWrapper + init with config param [OK]
Common Mistakes:
Missing @propertyWrapper attribute
No initializer with config parameter
Using functions instead of init for config
3. Consider this Swift code using a property wrapper with configuration:
@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)
}
}
struct Example {
@Clamped(range: 1...10) var number: Int = 5
}
var ex = Example()
ex.number = 15
print(ex.number)
What is the output when this code runs?
medium
A. 10
B. 5
C. 15
D. 1
Solution
Step 1: Understand the Clamped wrapper behavior
The wrapper clamps the value between the given range (1 to 10).
Step 2: Analyze the assignment and print
Assigning 15 triggers clamping to upper bound 10, so print outputs 10.
Final Answer:
10 -> Option A
Quick Check:
Value clamped to 10 [OK]
Hint: Remember clamping limits values to range [OK]
Common Mistakes:
Expecting original value 15 to print
Confusing initial value 5 with final
Ignoring clamping logic in setter
4. This Swift code attempts to use a property wrapper with configuration but causes a compile error:
@propertyWrapper
struct Limited {
var wrappedValue: Int
let max: Int
init(max: Int) {
self.max = max
self.wrappedValue = 0
}
}
struct Data {
@Limited(max: 100) var score: Int = 50
}
What is the main reason for the error?
medium
A. Cannot assign default value to score when using wrapper
B. Missing init(wrappedValue:max:) initializer to accept initial value
When using a default value on a wrapped property, the wrapper needs an initializer init(wrappedValue:max:) to accept it.
Step 2: Identify missing initializer
The code only has init(max:), so compiler cannot match score: Int = 50.
Final Answer:
Missing init(wrappedValue:max:) initializer to accept initial value -> Option B
Quick Check:
Init must accept wrappedValue when default given [OK]
Hint: Add init(wrappedValue:..., config...) for default values [OK]
Common Mistakes:
Thinking stored properties are disallowed
Believing default value assignment is invalid
Confusing let/var for causing error
5. You want to create a property wrapper Validated that checks a string against a minimum length and a regular expression pattern, both configurable. Which approach correctly supports this configuration and usage?
@propertyWrapper
struct Validated {
private var value: String
private let minLength: Int
private let pattern: String
var wrappedValue: String {
get { value }
set {
if newValue.count >= minLength && newValue.range(of: pattern, options: .regularExpression) != nil {
value = newValue
} else {
value = ""
}
}
}
// What initializer should be here?
}
struct User {
@Validated(minLength: 5, pattern: "^[a-zA-Z]+$") var username: String = ""
}