Issue #815

When ever a property marked with @Published change, ObservableObject will emit objectWillChange.send hence telling the View that observes it to reinvalidate.

In WWDC 2021 session Discover concurrency in SwiftUI they mention how objectWillChange is used to grab before-change data to diff the changes.

Screenshot 2021-06-30 at 14 08 54

In the below example, we have 2 ObservableObject

  • Store with just count value being used in the View, while flag is not used
  • Store2 with count not being used

But since the View observes these 2 objects, whenever any @Publish property changes, SwiftUI thinks that the data changes, then invalidates the body again to see if it needs to redraw.

class Store1: ObservableObject {
    @Published var count = 0
    @Published var flag = false
}

class Store2: ObservableObject {
    @Published var count = 0
}

struct ContentView: View {
    @StateObject var store1 = Store1()
    @StateObject var store2 = Store2()

    var body: some View {
        print("body called")
        return VStack {
            Text("Count \(store1.count)")
                .padding()

            Button(action: { store1.count += 1 }) {
                Text("Increase store1.count")
            }

            Button(action: { store1.flag.toggle() }) {
                Text("Flip store1.flag")
            }

            Button(action: { store2.count += 1 }) {
                Text("Increase store2.count")
            }
        }
    }
}

Even nothing changes

In this example, although we don’t change the value of our ObservableObject, body still gets called as any change trigger Publisher

class ViewModel: ObservableObject {
    @Published var flag = true
}

struct ContentView: View {
    @StateObject var viewModel = ViewModel()
    var body: some View {
        print("called")
        return VStack {
            Text("Hello, world!")
                .padding()
            Button(action: { viewModel.flag = true }) {
                Text("Click")
            }
        }
    }
}

Read more