I have encountered an issue with nested view updates that I don't understand. Maybe someone can explain what is happening.
In the code below the ContentView loads 2 views in succession. MyView1 followed by MyView2. MyView displays a button while MyView2 displays the value of its first argument. When the button is pressed MyView1 changes the value of its bound first argument. The ContentView is reloaded because of the change to its first argument. This results in MyView1 and MyView2 both being loaded again. Looked at from a procedural point of view this isn't what I was expecting.
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State var mydata1:Int = 0
@State var mydata2:Int = 1
var body: some View {
VStack {
Text("Hello world \(mydata1)")
MyView1(v1:$mydata1, v2:$mydata2)
Text(" myData1 = \(mydata1) myData2 = \(mydata2) ")
MyView2(v1:$mydata1, v2:$mydata2)
Text("Bye bye \(mydata1)")
}
}
}
struct MyView1:View {
@Binding var v1:Int
@Binding var v2:Int
var body: some View {
Text("MyView1")
if $v1.wrappedValue == 0 {
Button(action: {
$v1.wrappedValue = 10
}, label: {
Text("OK")
})
}
}
}
struct MyView2:View {
@Binding var v1:Int
@Binding var v2:Int
var body: some View {
Text("MyView2")
if $v1.wrappedValue == 0 {
Text("v1 = \(v1) v2 = \(v2) ")
}
else {
Text("???")
}
}
}
That's how SwiftUI works.
With the Binding on v1 in MyView1 and MyView2, each time you change the State variable v1 (through Bing in MyView1), that propagates to MyView2 through its own Binding.
Note: no need to use wrappedValue. This works:
Button(action: {
v1 = 10
}, label: {
Text("OK")
})
as well as
if v1 == 0 {
Text("v1 = \(v1) v2 = \(v2) ")
}
else {
Text("???")
}