Using Property Wrappers in iOS development iOS 05.08.2020

As the name suggests its a wrapper over the property, so you can change the raw value before returning it. You can think of property wrapper as a regular property, which delegates its get and set to some other type. Property wrappers can be used with struct, enum and class.

Property wrappers are a feature that was introduced in Swift 5.1 and they play a huge role in SwiftUI and Combine which are two frameworks that shipped alongside Swift 5.1 in iOS 13.

The idea of property wrappers, is that commonly used computed property getter and setter patterns can be encapsulated into a type with a wrappedValue computed property:

struct MyWrapper { 
    // ...
    var wrappedValue : SomeType { 
        get { /*...*/ }
        set { /*...*/ } 

You can then declare your computed property using the property wrapper type name as a custom attribute:

@MyWrapper var myProperty

The result is that, behind the scenes, a MyWrapper instance is created for you, and when your code gets or sets the value of myProperty, it is the getter or setter of this MyWrapper instance that is called.

In real life, your property wrapper’s purpose will almost certainly be to act as a facade for access to a stored instance property, declared inside the property wrapper’s type.

To implement your own property wrapper, you need to do a few things:

  • Declare a struct that will wrap the property.
  • Mark the struct as a @propertyWrapper before the struct keyword.
  • Implement the var wrappedValue computed variable. You can use get to get the value of the property, and set to set it. With this, you can see that you can let a property wrapper store its value anywhere.

To exemplify this, we will write a simple property wrapper that works with Strings and it changes them to uppercase letters.

struct Capitalized {
    private(set) var text: String = ""
    var wrappedValue: String {
        get { return text }
        set { text = newValue.uppercased() }

struct User {
    @Capitalized var firstName: String
    @Capitalized var lastName: String

var user = User(firstName: "Thomas", lastName: "Anderson")

user.lastName // prints ANDERSON

Another example

struct Rating {
    private var _rating: Int = 0

    var wrappedValue: Int {
        get {
            return _rating
        } set (value) {
            if value > 5 {
                _rating = 5
            } else if value < 1 {
                _rating = 1
            } else {
                _rating = value

struct MusicRating {
    @Rating var rating: Int

    init(rating: Int) {
        self.rating = rating

MusicRating(rating: 9)// prints 5
MusicRating(rating: 0)// prints 1

Styling UILabel

public class TitleLabel {
    public var wrappedValue: UILabel

    public init(text: String) {
        self.wrappedValue = UILabel()
        wrappedValue.text = text

    private func configureLabel() {
        wrappedValue.textColor = .lightGray
        wrappedValue.font = .systemFont(ofSize: 28, weight: .regular)

@TitleLabel(text: "The Matrix")
var titleLabel: UILabel


UserPreferences is a property wrapper that helps to save and get values from UserDefaults.

struct UserDefault<T> {
    let key: String
    let defaultValue: T

    init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue

    var wrappedValue: T {
        get {
            return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        set {
            UserDefaults.standard.set(newValue, forKey: key)

struct UserData {
    @UserDefault("hasVoted", defaultValue: false)
    static var hasVoted: Bool

UserData.hasVoted = true
print(UserData.hasSeenAppIntroduction) // prints false

Also you can extend UserDefault and save custom object.