skip to Main Content

I have one view "CancelRow", in which value of isSelected is changing

     struct CancelRow: View {
            @Binding var isSelected: Bool
        
            init(isSelected: Binding<Bool>) {
                self._isSelected = isSelected
            }
        
           @ViewBuilder var body: some View {
            HStack {
               Text(verbatim: "Hello, (isSelected)")
            }

            CustomCheckbox(checkboxType: .withTrailingLabel, 
             checkboxTitle: "", isActive: $canCancel, isSelected: $isSelected)
        }
        .onTapGesture {
                    isSelected.toggle()
                }
            }

I have another view i which i want to show button active or not based on "isSelected" from "CancelRow"

// AnotherVIew

CancelRow(isSelected: .constant(false))
    Spacer()
    SubmitButtonView(buttonTitle: title, buttonCallBack: {
        goToOtherScreen()
    }, isActive: isSelected ) // how to access this variable from  "CancelRow"

2

Answers


  1. As mentioned in the comments, state should be owned by a parent view and then passed to the child views.

    In your case, you don’t actually need to use a custom initializer for CancelRow in the example you gave (you could rely on just the synthesized initializer), but as request, this uses an initializer.

    struct CancelRow: View {
        @Binding var isSelected: Bool
        
        init(isSelected: Binding<Bool>) {
            self._isSelected = isSelected
        }
        
        @ViewBuilder var body: some View {
            HStack {
                Text(verbatim: "Hello, (isSelected)")
                Button("Toggle") {
                    isSelected.toggle()
                }
            }
        }
    }
    
    struct SubmitButtonView : View {
        var buttonTitle : String
        var buttonCallBack : () -> Void
        var isActive : Bool
        
        var body: some View {
            Text("Submit: (isActive ? "true" : "false")")
        }
    }
    
    struct ContentView: View {
        @State private var isSelected = false
        
        var title : String {
            "Title"
        }
        
        var body: some View {
            VStack {
                CancelRow(isSelected: $isSelected)
                SubmitButtonView(buttonTitle: title, buttonCallBack: {
                    goToOtherScreen()
                }, isActive: isSelected )
            }
        }
        
        func goToOtherScreen() {
            print("Navigate")
        }
    }
    
    Login or Signup to reply.
  2. There is this concept of Source of truth. In oversimplified terms, you need to have a @State private var in one of your structs. If that @State private var holds any information some other struct would like to use, the second struct should have @Binding var and be initialised from the first struct with the value of @State private var.

    In code below struct AnotherView is the source of truth, it has @State private var, and other structs have @Binding and are initialised with value of that @State private var.

    struct AnotherView:

    @State private var isSelected = false
    
    var body: some View {
        VStack {
            CancelRow(isSelected: $isSelected)
            
            Spacer()
            
            SubmitButtonView(isSelected: $isSelected)
        }
    }
    

    struct CancelRow:

    @Binding var isSelected: Bool
    
    var body: some View {
        Text(isSelected ? "I'm selected" : "I'm not selected")
    } 
    

    struct SubmitButtonView:

    @Binding var isSelected: Bool
    
    var body: some View {
        Button {
            // do something on tap
        } label: {
            Text("Button text")
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search