32

I am wanting to pass a Float Variable from one view to another new view.

In the code below there is a Float value called mhzValue which is set by way of the Slider, the slider changes the value and Text is then displaying within the view.. When the user taps on the Navigation Button to display the new view, I would like to be able to take the mhzValue and display it in the new view in a text box, as well as set it as another variable.

Hope that makes sense.

Please see some sample code below..

Thank you.

Craig

import SwiftUI
struct ContentView : View {
    @State private var mhzValue : Float = 0
    var body: some View {
        // Navigation View
        NavigationView {

            VStack{
                Text("Test Value:")
                    .font(.headline)
                    .color(.blue)
                    .padding(.leading, -180.0)

                //Get Slider Value
                Slider(value: $mhzValue, from: 1, through: 55, by: 1)
                    .padding(.horizontal)
                //Display Slider Value
                Text("\(Int(mhzValue)) Value")
                    .font(.title)
                    .fontWeight(.semibold)
                    .color(.blue)
                // Naviagtion Button and send value of mhzValue to new View
                NavigationButton(destination: NextView()){
                    Image(systemName: "plus.square.fill")
                        .foregroundColor(.white)
                        .font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
                        .frame(width: 150.0, height: 16.0)
                        .padding(15)
                        .background(Color.red)
                        .cornerRadius(10.0)
                }
            }
        }
    }
}

// New View to show Slider Value
struct NextView : View {
    var body: some View {
        Text("Display Slider Value Here:")

    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif
2
  • I see you've declared ContentView to be "the source of truth", to use Apple's term for mhzValue. Why is it set to private? That makes little sense. What happens if you remove that, and make sure NextView is binded to it? Without a bit more context, you might even just make it @EnvironmentObject. Commented Jun 30, 2019 at 2:01
  • Hi Thank you... I have been playing with Swift for a couple of years now and continue to have problems in remembering... Old age... Thanks for your comments they are much appreciated !! Craig Commented Jun 30, 2019 at 9:42

2 Answers 2

57

This is easily done with Bindings. Because mhzValue is marked with the @State property wrapper, it has an associated Binding. You can therefore declare a @Binding variable in your second view, and initialize it with the Binding to the original variable.

struct NextView : View {
    @Binding var mhzValue: Float
    ...
}

When you specify NextView as the destination for your navigation button, pass it a Binding to mhzValue. (The dollar-sign syntax is a shorthand way to refer to the binding.)

struct ContentView : View {
    @State private var mhzValue : Float = 0
    ...
    NavigationButton(destination: NextView(mhzValue: self.$mhzValue)){...}
    ...
}

You can then use mhzValue inside NextView:

struct NextView : View {

    @Binding var mhzValue: Float

    var body: some View {
        VStack{
            Text("Display Slider Value Here:")
            Text("\(Int(mhzValue)) Value")
                .font(.title)
                .fontWeight(.semibold)
                .color(.blue)
        }
    }
}

Any changes you make to mhzValue within NextView will effectively be changes to ContentView.mhzValue.

Sign up to request clarification or add additional context in comments.

3 Comments

Good answer. One question about it. As I noted in my comment, mhzValue is marked as private. Does this matter? (I'm actually surprised it builds without some warning or error.)
This is wonderful ... thank you... As I mention above I am having problems remembering ... I don't think I will ever grasp it.. therefore I will rely on people like you for your wonderful and continued help.. Thanks you .. Craig.
Thanks nice answer, i have one question for same.. How can we pass "mhzValue" to thirdView? is this possible in swiftUI?
5

The value can be passed through an init. i.e.

struct ViewToSendValue: View {
    var body: some View {
        ViewToReceiveValue(valueToPass: "some string")
    }
}

struct ViewToReceiveValue: View { 

    var valueToPass: String = ""

    init(valueToPass: String) {
        self.valueToPass = valueToPass
    }

    var body: some View {
        Text(valueToPass)
    }
}

6 Comments

That's the easiest method so far.
But that only happens once. So if you make a change on the first view to that value, it won't reflect in the second view.
@trilogy that isn't true. You can try it out in a sample project.
@Hayden an “init” is like a constructor, it only runs once on creation. Using Bindings is the correct way.
"an “init” is like a constructor, it only runs once on creation" is correct, but SwiftUI will re-initialize the view if its dependencies change. In the above example, if you create a mechanism to change valueToPass at runtime (like pressing a button), and add a breakpoint in ViewToReceiveValue.init, you can see that it's called once on launch, and once after the button is pressed. This approach is preferred (and just as performant) over bindings if you want one-way data flow. Bindings allow the child to modify the property connected to the parent, which isn't always desirable.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.