Reputation: 15872
I have a problem like this one, but @Binding
doesn't seem like a good solution for it. I have a view that has child views, which have their own child views, and so on. They all have a label
attribute. If I click a button, I want to set the labels for all the views down the whole tree. The code I have is something like this:
@State var label:String = ""
func setLabel(l:String) {
label = l
for c in children {
c.setLabel(l)
}
}
This doesn't work, but if I change label
to an ObservedObject
, it works:
class Label: ObservableObject {
@Published var label:String = ""
func setLabel(_ s:String) {
label = s
}
}
@ObservedObject var label:Label = Label()
I don't want to create a new wrapper class each time I have to do this, though. Is there a different way?
Upvotes: 0
Views: 37
Reputation: 257779
Single source of truth, in this scenario we need only one @State
, and then all hierarchy will be updated correctly...
Here is a demo. Prepared with Xcode 12.1 / iOS 14.1
struct ContentView: View {
@State private var label = "-1"
var body: some View {
VStack {
Button("Update") { self.label = "\(Int.random(in: 0...9))" }
Text("Main: \(label)")
ChildDemoView(label: label)
}
}
}
struct ChildDemoView: View {
let label: String
var level = 1
var body: some View {
VStack {
Text("Child\(level): \(label)")
if level < 10 {
ChildDemoView(label: label, level: level + 1)
}
}
}
}
Upvotes: 1