Swift Tutorial · Advanced Swift · Lesson 26 of 30
Swift Property Wrappers
Reuse property logic with property wrappers, the feature behind SwiftUI's @State and @Binding.
@propertyWrapper
A property wrapper is a type with a wrappedValue that adds behaviour to any property it's applied to:
validation, clamping, persistence or change tracking. SwiftUI's @State, @Binding and @Environment are
property wrappers. A projectedValue is exposed with $name.
@propertyWrapper
struct Clamped {
private var value: Int
let range: ClosedRange<Int>
private(set) var projectedValue = 0 // how many times a value was clamped
init(wrappedValue: Int, _ range: ClosedRange<Int>) {
self.range = range
self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
}
var wrappedValue: Int {
get { value }
set {
let clamped = min(max(newValue, range.lowerBound), range.upperBound)
if clamped != newValue { projectedValue += 1 }
value = clamped
}
}
}
struct Player {
@Clamped(0...100) var health = 100
}
var player = Player()
player.health -= 30
print(player.health)
player.health += 80
print(player.health)
player.health = -5
print(player.health, "clamped \(player.$health) times")
Output
70 100 0 clamped 2 times
Run this on your computer — see “Get Started” for setup.
Test yourself
Which SwiftUI feature is built on property wrappers?
@MainActor@State and @Binding@escaping@objc
Show answer
Answer: @State and @Binding