Introduction

SwiftUI's property wrappers elevate your properties beyond simple data storage. They grant you the ability to add functionality, interact with the view lifecycle, and manage data in a structured way. This article unveils how to construct custom property wrappers and explores their potential through practical examples.

How do we create a property wrapper?

  1. Add @propertyWrapper annotation in any struct or class.
  2. Provide a stored property wrappedValue. Here is where we can add our custom logic.
@propertyWrapper
struct RemoveWhiteSpace {
    var wrappedValue: String {
        didSet { wrappedValue = wrappedValue.trimmingCharacters(in: .whitespaces) }
    }
    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue.trimmingCharacters(in: .whitespaces)
    }
}

To use the above custom property wrapper, we just need to add @RemoveWhiteSpace to the property we want.

struct User {
    @RemoveWhiteSpace var fullName: String
}

let user = User(fullName: "John Doe        ")
print(user.fullName)

// Output : John Doe

Let's create a property wrapper for persisting data using UserDefaults. This wrapper will automatically save and load values:

@propertyWrapper
struct UserDefaultsWrapper<Value: Codable> {
  let key: String
  private var wrappedValue: Value

  init(key: String) {
    self.key = key
    self.wrappedValue = UserDefaults.standard.object(forKey: key) as? Value ?? // Set default value
  }
  var wrappedValue: Value {
    get { return self.wrappedValue }
    set {
      UserDefaults.standard.set(newValue, forKey: key)
      // Optionally, handle errors or notifications here
    }
  }
}

In this example

Usage Example

@StateObject
private var userSettings = UserDefaultsWrapper<Settings>(key: "user_settings")

Here, we create a UserDefaultsWrapper instance named userSettings that holds a Settings struct. Any changes to userSettings.wrappedValue will automatically persist in UserDefaults.

Exploring Possibilities

Custom property wrappers offer a wide range of functionalities beyond data persistence. Here are some additional examples:

Conclusion

By leveraging custom property wrappers, you can streamline data management, enforce validation rules, and tailor your views based on the environment, all within a clean and organized structure.