Property Wrappers in Swift
Tags: swift, propertywrappers, designpatterns, ios
Published: 2024-03-29 21:48:49

Property wrappers in Swift are a powerful feature that allows developers to add a layer of separation between the code that manages how a property is stored and the code that defines a property. By encapsulating the logic for storing, retrieving, and observing property changes, property wrappers make it easier to reuse code, enforce validation, and manage storage in a clean, modular way.

## Introduction to Property Wrappers
A property wrapper is a generic structure that encapsulates read and write access to the property and can add additional behavior. You define a property wrapper by creating a structure, enumeration, or class that defines a wrapped value. You apply a property wrapper to a property by writing the wrapper’s name before the property as an attribute.

## Defining a Property Wrapper
To define a property wrapper, you declare a structure, enumeration, or class with the `@propertyWrapper` attribute. The wrapped value is represented by a property named `wrappedValue`. Consider this straightforward example that capitalizes strings.
```swift
@propertyWrapper
struct Capitalized {
    private var value: String

    var wrappedValue: String {
        get { value }
        set { value = newValue.capitalized }
    }

    init(wrappedValue initialValue: String) {
        self.value = initialValue.capitalized
    }
}
```
With this, any `String` you assign gets automatically capitalized. It’s like having an editor who makes sure every title looks just right.

## Using Property Wrappers
Let’s put our `Capitalized` wrapper into action. You do this by prefixing a property with `@Capitalized`.
```swift
struct Person {
    @Capitalized var name: String
}

var person = Person(name: "john doe")
print(person.name) // Prints "John Doe"
```
In this example, `@Capitalized` ensures that `name` is always stored with a capitalized value, regardless of how it was originally set.

## Combining Property Wrappers
Why stop at one? You can apply multiple property wrappers to a property by stacking them. Here’s how you might combine a property wrapper that trims whitespace with our `Capitalized` wrapper.
```swift
@propertyWrapper
struct Trimmed {
    private var value: String = ""

    var wrappedValue: String {
        get { value }
        set { value = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
    }

    init(wrappedValue initialValue: String) {
        self.value = initialValue.trimmingCharacters(in: .whitespacesAndNewlines)
    }
}

struct Person {
    @Trimmed @Capitalized var name: String
}

var person = Person(name: "  john doe  ")
print(person.name) // Prints "John Doe"
```
## Accessing a Property Wrapper’s Additional Functionality
Property wrappers can also expose additional functionality by defining properties and methods outside the `wrappedValue`. For instance, consider a property wrapper that keeps track of whether the property has been accessed.
```swift
@propertyWrapper
struct Accessed {
    private var value: Int
    private(set) var accessed: Bool = false

    var wrappedValue: Int {
        get {
            accessed = true
            return value
        }
        set { value = newValue }
    }

    init(wrappedValue initialValue: Int) {
        self.value = initialValue
    }
}

struct Data {
    @Accessed var number: Int
}

var data = Data(number: 42)
print(data.number) // Accesses the number, setting accessed to true
print(data.$number.accessed) // Prints "true"
```
Here, `$number` provides direct access to the property wrapper instance, allowing you to access its accessed property.

## Summary
Property wrappers in Swift are a powerful feature that significantly streamlines the way you handle properties in your code. By encapsulating the logic for property storage and manipulation, they help you maintain a clean and modular codebase. Whether you’re looking to enforce specific property constraints or automate certain behaviors, property wrappers provide an effective solution.

---

For anyone looking to deepen their understanding of property wrappers, the _Swift Programming Language Guide_ offers foundational knowledge, syntax, and usage patterns. Additionally, _Swift Evolution Proposal SE-0258_ provides detailed insights into the motivation, design, and practical use cases of property wrappers within the Swift language. Exploring these resources will equip you with the knowledge to leverage property wrappers fully in your Swift projects.