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.

Create a free account to save this page, take notes and track your progress. Sign in

@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.

A clamping property wrapper
@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?

  1. @MainActor
  2. @State and @Binding
  3. @escaping
  4. @objc
Show answer

Answer: @State and @Binding

Was this page helpful?