0

I am facing a problem with property changes are not being watched in my view. The problem appears when I use class. However, when I use Struct instead of class the problem is solved.

Code which is working:

struct DetailsModel {
    var dayState : Bool
    init() {
        dayState = true
    }
}

class ViewModel : ObservableObject{
    @Published var charge = DetailsModel()
}

struct ContentView: View {
    //@StateObject var viewModel = ViewModel()
    @StateObject var viewModel = ViewModel()
    var body: some View {
        VStack{
            HStack{
                Text(viewModel.charge.dayState == true ? "Day" : "Night")
                    .padding()
                Button.init {
                    viewModel.charge.dayState.toggle()
                } label: {
                    Text("Toggle")
                }
            }
        }
    }
}

When I tap the Toggle Button, the text views are changing Day/Night.

Code which is not working:

I replace the struct with class and it's not updating the view.

class DetailsModel: ObservableObject {
    @Published var dayState : Bool
    init() {
        dayState = true
    }
}

My question is As I already using ObserableObject and as well as Published properties in Details class, it should be watch the object , why its not observing anything from the View?

Shourob Datta
  • 1,886
  • 22
  • 30
  • You don't need to edit the question; it's clear. And so is the answer. Please read the link I gave you. It explains this clearly and completely. When `charge` is a DetailsModel and DetailsModel is a class, mutating the DetailsModel `dayState` property doesn't replace the value of `charge`, so there is no change to observe. But when `charge` is a DetailsModel and DetailsModel is a struct, mutating the DetailsModel `dayState` property _does_ replace the value of `charge`, so there is a change of object and the update is triggered. – matt Mar 22 '22 at 12:17
  • "When charge is a DetailsModel and DetailsModel is a class, mutating the DetailsModel dayState property doesn't replace the value of charge, so there is no change to observe." I got this clearly. But DetailsModel class is not a normal class. I use ObservableObject protocol, and Published wrapper to the dayState to catch the event into ViewModel. So the fact should be like. Change dayState -> inform the change to the charge of ViewModel -> ViewModel inform the changes to view. My question why this cycle not happening? – Shourob Datta Mar 22 '22 at 12:31
  • "I got this clearly" I don't think so. You're just making up the idea that the `@Published` property will somehow magically change the laws of mutation and observation. It doesn't. The "cycle" doesn't "happen" because a mutation of a class instance is not a change of value. _You_ can trigger the signal that the observed object will change, but the `@Published` wrapper won't do it for you. – matt Mar 22 '22 at 13:44
  • Thank you for your reply. Published variable only published/fired if there anything any changes in value types, not in a reference type. This is the summary, isn't it? – Shourob Datta Mar 22 '22 at 22:50
  • A `@Published` variable is published when it is set. Mutating a reference type doesn't set it. Mutating a value type does. – matt Mar 22 '22 at 23:13
  • Thank you mat. Another thing is if you change a value of struct. it destroys and reconstructs. How could I prove this? like viewModel.charge.dayState == true. then DetailsModel struct will recreate. – Shourob Datta Mar 23 '22 at 12:01
  • Did you look at the link I gave you? – matt Mar 23 '22 at 12:58

0 Answers0