Update parent view from child in SwiftUI
If we want to change or update the value of any property in SwiftUI, we use the State property wrapper. SwiftUI keeps track of State properties and automatically updates all the views using these state properties whenever their value changes.
But the thing to notice here is state properties don’t work outside their current scope. This means state properties are only for the UIView in which they are declared. You cannot use them outside of their view. Therefore, you cannot update a View from a different View by using state properties.
So here comes the Binding Property wrapper, Which helps us bind two views. You can use binding property to update the parent view from the child view.
Let’s see how to use a binding property wrapper.
Using binding property to update the parent view from the child view
struct ParentView: View { @State var score = 0 var body: some View { VStack{ Text("Score: \(score)").padding().fontWeight(.bold) //calling child view in parentview childView() } .navigationTitle("Tap and Play") } } struct childView:View{ var body: some View{ Button(action: { }, label: { Text("Tap").foregroundColor(Color.white) }).frame(width: 200,height: 40,alignment: .center) .background(Color.blue) } }
So there are two views, Parent View and Child View, and the child view is called inside the parent view.
and there is also a state property named score which we’ll later use to bind the child view to the parent view. Then we will update the parent property value from the child view using a binding property wrapper.
Now add a binding property inside the ChildView.
struct childView:View{ @Binding public var score:Int var body: some View{ Button(action: { score += 1 }, label: { Text("Tap").foregroundColor(Color.white) }).frame(width: 200,height: 40,alignment: .center) .background(Color.blue) } }
- @Binding is used for declaring binding properties.
- Binding properties should be public.
- Binding properties don’t accept any default value as their value comes from the parent.
- Use binding property wrapper to read and write data between parent and child views.
We have added a binding property inside the child view. So now we have to update the childView constructor inside the Parent View.
struct ParentView: View { @State var score = 0 var body: some View { VStack{ Text("Score: \(score)").padding().fontWeight(.bold) // Binding parent view to child view childView(score: $score) } .navigationTitle("Tap and Play") } }
We have passed the state score property to the child view constructor, which accepts a binding property, and a state property gets converted into a binding property using $ notation.
Whenever the button inside the childView gets pressed it updates the score property value. Which is the binding property thus it updates the textView showing the score property inside the parent View.
Here’s the complete code for reference
import SwiftUI struct ParentView: View { @State var score = 0 var body: some View { VStack{ Text("Score: \(score)").padding().fontWeight(.bold) // Binding parent property to child property childView(score: $score) } .navigationTitle("Tap and Play") } } struct childView:View{ @Binding public var score:Int var body: some View{ Button(action: { //updating parent propety in child view score += 1 }, label: { Text("Tap").foregroundColor(Color.white) }).frame(width: 200,height: 40,alignment: .center) .background(Color.blue) } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ParentView(score: 0) } }
Leave a Reply