A coworker came up with the following SwiftUI example which looks like it works just as expected (you can enter some text and it gets mirrored below), but how it works is surprising to me!
import SwiftUI
struct ContentView: View {
@State var text = ""
var body: some View {
VStack {
TextField("Change the string", text: $text)
WrappedText(text: $text)
}
}
}
struct WrappedText: View {
@Binding var text: String
var body: some View {
Text(text)
}
}
My newbie mental model of SwiftUI led me to think that typing in the TextField would change the $text
binding, which would in turn mutate the text
@State var. This would then invalidate the ContentView
, triggering a fresh invocation of body
. But interestingly, that's not what happens! Setting a breakpoint in ContentView's body
only gets hit once, while WrappedText's body
gets run every time the binding changes. And yet, as far as I can tell, the text
state really is changing.
So, what's going on here? Why doesn't SwiftUI re-invoke ContentView's body on every change to text
?