DEV Community

Cover image for Property Wrappers in Swift
Josh Lang
Josh Lang

Posted on

Property Wrappers in Swift

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.

@propertyWrapper
struct Capitalized {
    private var value: String

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

    init(wrappedValue initialValue: String) {
        self.value = initialValue.capitalized
    }
}
Enter fullscreen mode Exit fullscreen mode

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.

struct Person {
    @Capitalized var name: String
}

var person = Person(name: "john doe")
print(person.name) // Prints "John Doe"
Enter fullscreen mode Exit fullscreen mode

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.

@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"
Enter fullscreen mode Exit fullscreen mode

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.

@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"
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)