Below is an example of a parent ContentView with State and a child Sidebar with a Binding.
The didSet is only called for the property that is changed.
When we click Button in ContentView, that changes State property, so only the didSet in ContentView is called When we click Button in Sidebar, that changes Binding property, so only the didSet in Sidebar is called
var body: some View { Sidebar(tag: $tag) Button(action: { tag = .settings }) { Text("Button in ContentView") } } }
structSidebar: View{ @Binding var tag: Tag { didSet { print("Sidebar \(tag)") } }
var body: some View { Text(tag.rawValue) Button(action: { tag = .settings }) { Text("Button in Sidebar") } } }
Custom Binding with get set
Another way to observe Binding changes is to use custom Binding with get, set. Here even if we click Button in ContentView, the set block is triggered and here we can change State
1 2 3 4 5 6 7 8 9 10 11 12
var body: some View { Sidebar(tag: Binding<Tag>( get: { tag }, set: { newTag in self.tag = newTag print("ContentView newTag \(newTag)") } )) Button(action: { tag = .settings }) { Text("Button in ContentView") } }
Convenient new Binding
We can also make convenient extension on Binding to return new Binding, with a hook allowing us to inspect newValue. So we can call like Sidebar(tag: $tag.didSet