Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View refreshing not triggered when ObservableObject is inherited in SwiftUI

ContentView2 view is not refreshed when model.value changes, if Model conforms to ObservableObject directly instead of inheriting SuperModel then it works fine

class SuperModel: ObservableObject {

}

class Model: SuperModel {
    @Published var value = ""
}

struct ContentView2: View {

    @ObservedObject var model = Model()

    var body: some View {
        VStack {
            Text(model.value)
            Button("change value") {
                self.model.value = "\(Int.random(in: 1...10))"
            }
        }

    }
}
like image 225
Sorin Lica Avatar asked Mar 16 '20 08:03

Sorin Lica


2 Answers

Here is working variant of your example. See that to be able to work, not only chaining the publishers is required, but at least one Published property. So or so, it could help in some scenario.

import SwiftUI

class SuperModel: ObservableObject {
    // this is workaround but not real trouble.
    // without any value in supermodel there is no real usage of SuperModel at all
    @Published var superFlag = false
}

class Model: SuperModel {
    @Published var value = ""
    override init() {
        super.init()
        _ = self.objectWillChange.append(super.objectWillChange)
    }
}

struct ContentView: View {

    @ObservedObject var model = Model()

    var body: some View {
        VStack {
            Text(model.value)
            Button("change value") {
                self.model.value = "\(Int.random(in: 1...10))"
            }
        }

    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

changing the code to

var body: some View {
        VStack {
            Text(model.value)
            Button("change value") {
                self.model.value = "\(Int.random(in: 1...10))"
            }
            Text(model.superFlag.description)
            Button("change super flag") {
                self.model.superFlag.toggle()
            }
        }

    }

you can see how to use even your supermodel at the same time

enter image description here

like image 179
user3441734 Avatar answered Oct 18 '22 17:10

user3441734


Use ObjectWillChange to solve the problem specified.

Here is the working code:

import SwiftUI

class SuperModel: ObservableObject {

}

class Model: SuperModel {
    var value: String = "" {
        willSet { self.objectWillChange.send() }
    }
}

struct ContentView: View {

    @ObservedObject var model = Model()

    var body: some View {
        VStack {
            Text("Model Value1: \(model.value)")
            Button("change value") {
                self.model.value = "\(Int.random(in: 1...10))"
            }
            Text("Model Value2: \(model.value)")
        }
    }
}
like image 31
Subha Narayanan Avatar answered Oct 18 '22 19:10

Subha Narayanan