[SOLVED] Sharing a @State var Bool between 2 child Views in SwiftUI

Issue

I’m a designer who’s trying to learn SwiftUI for fun and also to make sure I know a bit more what my developer’s team needs from me.

And there’s something very simple I just can’t do!

As you can see from this piece of code below, I just want to show a text when the var showHello is true, and it’s working nicely.

import SwiftUI

struct ContentView: View {

    @State var showHello = true

    var body: some View {

        VStack {
            Spacer()
            Button("Show Hello", action: { showHello.toggle() })
                .padding()
            Spacer()
            Text("This is your message:")
                .padding()
            if showHello == true {
                Text("Hello")
            } else {
                Text("Hello")
                    .opacity(0)
            }
            Spacer()
        }

    }

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

But when I want to do the exact same thing by using multiple views, it doesn’t work!

// Parent file

import SwiftUI

struct ContentView: View {

    var body: some View {

        VStack {
            TopView()
            BottomView()
        }

    }

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
// Child file 1

import SwiftUI

struct TopView: View {

    @State var showHello = true

    var body: some View {

        Button("Show Hello", action: { showHello.toggle() })
            .padding()

    }

}

struct TopView_Previews: PreviewProvider {
    static var previews: some View {
        TopView()
    }
}
// Child file 2

import SwiftUI

struct BottomView: View {

    var body: some View {

        Text("This is your message:")
        if showHello == true {
            Text("Hello")
        } else {
            Text("Hello")
                .opacity(0)
        }

    }

}

struct BottomView_Previews: PreviewProvider {
    static var previews: some View {
        BottomView()
    }
}

And I know that we can’t share a var from different views so I have spent hours on Internet to learn more about using @State/@Binding or @EnvironmentObject but all the examples are about sharing a var from a parent view to a child view but not between child views into a parent view.

Also, no matter what I’m doing, there’s always an error from Xcode because something is missing somewhere!

I need your help, thanks in advance! 😛

Solution

I have spent hours on Internet to learn more about using @State/@Binding or @EnvironmentObject

So you are on the right path because you do need to use @Binding. Maybe you just had the wrong idea of how to connect the dots.

Basically you need the @State property wrapper in your parent or ContentView and since you want to share that same property in your child views and react to any mutation on it, you use the @Binding property wrapper in the child views.

So you would have something like this:

struct ContentView: View {
    @State var showHello = true

    var body: some View {
        VStack {
            TopView(showHello: $showHello)
            BottomView(showHello: showHello)
        }
    }
}

struct TopView: View {
    @Binding var showHello: Bool

    var body: some View {
        Button("Show Hello", action: { showHello.toggle() })
            .padding()
    }
}

struct BottomView: View {
    let showHello: Bool

    var body: some View {
        Text("This is your message:")
        Text("Hello")
            .opacity(showHello ? 1 : 0)
        }
    
}

I would recommend some other good resources for SwiftUI:

Answered By – NicolasElPapu

Answer Checked By – Terry (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *