Swiftui Change on Multilevel Children Published Object Change

SwiftUI change on multilevel children Published object change

Observable objects don't just work when you have multiple levels of classes. The @Published property wrapper notifies the view when the property has changed, but because this property is a class - a reference type - it doesn't actually change when you change one of its properties. In other words, the reference remains the same.

And the inner @Published doesn't do anything because there's nothing directly observing it (even if RecordingTimeManager conformed to an ObservableObject)

So, you either need to make RecordingTimeManager a value-type - a struct:

struct RecordingTimeManager {
var maxRecordingTime: TimeSeletedTime = .sixteenSeconds
}

Or, if it must be a class (perhaps because it has some internal state and life cycle), then you could create an inner view that directly observes it.

First, it needs to be an ObservableObject:

class RecordingTimeManager: ObservableObject {
@Published var maxRecordingTime: TimeSeletedTime = .sixteenSeconds

and then create a view (could be a private internal view) that observes it:

struct MainView: View {
@StateObject var appStatus: AppStatus = .init()

private struct InnerView: View {
@ObservedObject var recordingManager: RecordingTimeManager

var body: some View {
Button {
recordingManager.maxRecordingTime = .fifteenSeconds
} label: {
Text("15")
.font(Font.custom("BwGradual-Bold", size: 15))
.foregroundColor(
recordingManager.maxRecordingTime == .fifteenSeconds
? CLAPSOFFWHITE : TRIBESGREY)
}
}
}

var body: some View {

InnerView(recordingManager: appStatus.recordingTimeManager)
}
}

SwiftUI: How to change @Published object value. Changing a value of a published variable is not working

Solution

Change DCViewModel to struct.

Or if you have to keep it as a class, make DCViewModel conform to ObservableObject , and keep a single reference in every singleView. (which means you should subtract that row as a single View)



Explanation

@Published is a property wrapper that publishes change message only when the wrapped value has been set.

The difference between value type and reference type: when you change a variable that holds a value type(struct), it has been set a new value actually. But when you change the value of a reference type(class), the variable that points to that object won't change.

That's why, in your case, when you add a new DCViewModel to the Array(value type), you are always setting a new value to that array, so @Published takes effect. However, the wrapped value is DCViewModel, which is a class(reference type). When you change DCViewModel's value, the wrapped value's setter will not be called and @Published won't publish messages.

SwiftUI - changes in nested View Model classes not detected using onChange method

Figure it out. Just had to create another AnyCancellable variable to call objectWillChange publisher.

WatchDayProgramViewModel

class WatchDayProgramViewModel: ObservableObject {

@Published var workoutModel = WorkoutModel()
var cancellable: AnyCancellable?

init() {
cancellable = workoutModel.objectWillChange
.sink { _ in
self.objectWillChange.send()
}
}

}

While I have provided my answer, that worksaround with viewmodels, I would love to see/get advice on other alternatives.

SwiftUI - Change an @Published var from one view and have it reflect on another

If ExerciseSelector and its array is your "single source of truth" then you need to do something like you have already done so that both views can use the same instance. Another option to look into is to use a @EnvironmentObject which is a different way of achieving basically the same. See this article for instance to learn about EnvironmentObject

Dynamically changing colors with @State or @ObservableObject using static functions in Swift

Dynamically changing colors with @State or @ObservableObject using static functions in Swift

Simple answer: this is not possible.

Simple reason: @Published works only on instance var and not static


As there is missing context I just asume you want to change the colors from different views. If thats the reason for implementing the function as static there is a workaround.

Instantiate your ColorChangingClass at the top most View that uses it as a @StateObject. Hand it down to the child views via .environmentObject().

If you provide more context there could be other possible solutions too.

Change the @Published object value without triggering the didSet {}?

Why not simply use a custom method where you could selectively do the following functionality using a boolean check. For Example:

func setParameters(_ parameters: [String: String], andLoad load: Bool) {
dicParameters = parameters
if load {
loadDemos()
}
}

variable in observable object not accessible after declaration (SwiftUI)

The problem was, that I instantiated the PostRepository at two different locations. I solved the problem, by declaring a global variable instead.



Related Topics



Leave a reply



Submit