[SwiftUI][Combine] @Published is a property wrapper for providing publisher

In this post, let's take a look at @Published from another point of view.

Environment

Foloowing environment is used.

  • macOS Big Sur 11.2.1
  • Xcode 12.4

@Published

If you add @Published to the properties, then the change in the property will be propagated to the views. i.e. Views will be updated automatically.

You can see this explanation about @Published everywhere.

But in Apple documentation, they say "A type that publishes a property marked with an attribute."

Apple documentation is here.

So let's try to fill the gap.

@Published is a part of Combine framework

In Apple documentation, you will find @Published is NOT a part of SwiftUI, it comes from Combine.

@Published will make Publisher

Actually @Published can be used not only for updating views but also for other purpose.

if you add @Published to the property, you can access to the Publisher of the property with using $ (i.e. projectedValue).

This means @Publisher will make Publisher.

Here is the example code which comes from Apple doc.

example from Apple

class Weather {
    @Published var temperature: Double
    init(temperature: Double) {
        self.temperature = temperature
    }
}

let weather = Weather(temperature: 20)
cancellable = weather.$temperature
    .sink() {
        print ("Temperature now: \($0)")
}
weather.temperature = 25

// Prints:
// Temperature now: 20.0
// Temperature now: 25.0

observe variable

observation in old fashion

From the beginning, Swift provide the observation feature like following.

example which works on Playground

import Foundation

class Test {
    var test2:Int = 10 {
        willSet{
            print("willSet (\(test2) -> \(newValue))")
        }
        didSet{
            print("didSet (\(oldValue) -> \(test2))")
        }
    }
}

func update(test:Test) {
    test.test2 += 1
}

let test = Test()

test.test2 = 11   // 10 -> 11

update(test:test)  // 11 -> 12

// Prints:
//willSet (10 -> 11)
//didSet (10 -> 11)
//willSet (11 -> 12)
//didSet (11 -> 12)

Observation in Combine-style is @Published

@Published is the Combine-style to observe variables.

With attaching @Published, Swift will provide the Publisher for that property.

You can access the publisher with "$", then using sink/assign, you can react the change in that property.

In this Combine-style, not only one but also many can subscribe the publisher. Then can react the change.

View update in SwiftUI

View updating in SwiftUI is implemented with @Published and Observable/@ObservedObject.

If a class is conform to ObservableObject, which means the class should have "objectWillChange" property. This "objectWillChange" is a Publisher.

Apple documentation is here.

When the @Published variable is changed, before happing actual change in variable, it will be notified to "objectWillChange". If someone is subscribing "objectWillChange", someone will also be notified.

This is the things what is happening in the SwiftUI view update.

Note: There are many protocol, property wrappers for this mechanism. "@Published", "ObservableObject", "@ObservedObject". but only "@ObservedObject" is the element comes from SwiftUI.
others come from Combine.

This indicates how nicely SwiftUI and Combine is combined.

In the past, I believed ObservableObject and @ObserevedObject should come from same framework, but it is NOT true. ObservableObject comes from Combine, @ObservedObject comes from SwiftUI.

Summary:@Published makes publisher for variable observation in Combine-style

@Published makes publisher for variable observation in Combine-style
  • willSet/didSet (variable observation in old style) can be replaced with @Published from Combine.
  • View updating in SwiftUI comes from the combination of @Published/ObservableObject/@ObservedObject which comes from both SwiftUI and Combine.

Your comments are highly appreciated. please feel free to contact to twitter.

Leave a Reply

Your email address will not be published. Required fields are marked *