Home > OS >  Binding a button leads to "Missing argument for parameter in call" error
Binding a button leads to "Missing argument for parameter in call" error

Time:09-18

I'm trying to create a Binding in two views so I can change something on one side and have it reflected on the other.

I basically have:

  • a circle on both views
  • a button to change the other view's circle color
  • and one to go to the other view

It all works fine if I only have a Binding in the "ColorChange2" view, but when I add a Binding in "ColorChange1" I get into trouble.

It tells me: Missing argument for parameter 'isOn2'. But when I add isOn2 into ColorChange1() it wants a binding, but if I do ColorChange1(isOn2: $isOn2) it says it can't find '$isOn2' in scope.

I found one solution suggesting to add .constant(true)) into the preview but since it's a constant, it wont change the view like I wanted since it's a constant.

What can I do to make it work?

Code:


struct ColorChange1: View {
    
    @State private var isOn = false
    @Binding var isOn2 : Bool
    
    var body: some View {
        NavigationView {
            VStack {
                Circle()
                    .fill(isOn ? .green : .red)
                    .frame(width: 100)
                
                Button(action: {
                    isOn2.toggle()
                }, label: {
                    Text("Change button view 2")
                        .padding()
                })
                
                NavigationLink(destination: {
                    ColorChange2(isOn: $isOn)
                }, label: {
                    Text("Go to view 2")
                })
            }
        }
    }
}

struct ColorChange2: View {
    
    @Binding var isOn : Bool
    @State private var isOn2 = false
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        VStack {
            Circle()
                .fill(isOn2 ? .green : .red)
                .frame(width: 100)
            
            Button(action: {
                isOn.toggle()
            }, label: {
                Text("Change button view 1")
                    .padding()
            })
            
            Button(action: {
                dismiss.callAsFunction()
            }, label: {
                Text("Go to view 1")
            })
        }
        .navigationBarBackButtonHidden(true)
    }
}

struct ColorChange_Previews: PreviewProvider {
    static var previews: some View {
//        ColorChange(isOn2: .constant(true))
        ColorChange1()
    }
} ```

CodePudding user response:

You don't need both @Binding value in both screen to connect between screen like that.

@Binding means that get the value in @State of the first view and make a connection in the second view. In this scenero, when you go back from second view, it was dismissed.

For your problem, make an ObservableObject to store value. 1 for present in first view and 1 for second view. Then add it to second view when ever you need to display.

Code will be like this

class ColorModel : ObservableObject {
    @Published var isOnFirstView = false
    @Published var isOnSecondView = false
    
    func didTapChangeColor(atFirstView: Bool) {
        if atFirstView {
            isOnSecondView = !isOnSecondView
        } else {
            isOnFirstView = !isOnFirstView
        }
    }
}

struct ColorChange2: View {
    // binding model
    @ObservedObject var colorModel : ColorModel
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        VStack {
            Circle()
                .fill(colorModel.isOnSecondView ? .green : .red)
                .frame(width: 100)
            
            Button(action: {
                colorModel.didTapChangeColor(atFirstView: false)
            }, label: {
                Text("Change button view 1")
                    .padding()
            })
            
            Button(action: {
                dismiss.callAsFunction()
            }, label: {
                Text("Go to view 1")
            })
        }
        .navigationBarBackButtonHidden(true)
    }
}


struct ColorChange1: View {
    @StateObject private var colorModel = ColorModel()
    
    var body: some View {
        NavigationView {
            VStack {
                Circle()
                    .fill(colorModel.isOnFirstView ? .green : .red)
                    .frame(width: 100)
                
                Button(action: {
                    colorModel.didTapChangeColor(atFirstView: true)
                }, label: {
                    Text("Change button view 2")
                        .padding()
                })
                
                NavigationLink(destination: {
                    ColorChange2(colorModel: colorModel)
                }, label: {
                    Text("Go to view 2")
                })
            }
        }
    }
}


struct ColorChange_Previews: PreviewProvider {
    static var previews: some View {
        ColorChange1()
    }
}
  • Related