Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass variable from one view to another in SwiftUI

Tags:

ios

swiftui

I'm trying to pass one variable from one view to another in SwiftUI. I have a reset button in which I want to set the variable to zero in the other view.

I have tried creating a new struct in view one and accessing that variable in view 2.

// View 1

@State var count = MyNumber.number

// Body of app

Button(action: {self.count = self.count-10}) {
                    Text("-")   
                }
Text("\(count)")

struct MyNumber {
    static var number = 0
}

// View 2

 @State var countit = MyNumber.number

// Body

Button(action: {self.countit = 0}) {
            Text("Reset")
            }

Text in view one is still showing the number that was computed in View 1

like image 370
iruleee Avatar asked Oct 18 '19 16:10

iruleee


People also ask

How do I pass a binding variable in SwiftUI?

The best solution here (to my opinion) is custom Bindings with a a wrapper View. That will give you two choices: Bind your (child) View with the parent View so that both parent and child can change the value. Don't bind child View with parent so that ONLY the child will save the value internally.

What does @state do in SwiftUI?

With @State, you tell SwiftUI that a view is now dependent on some state. If the state changes, so should the User Interface. It's a core principle of SwiftUI: data drives the UI.

What is var body some view in SwiftUI?

'some' means opaque type. In SwiftUI, View is declared as a protocol @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *) public protocol View { /// The type of view representing the body of this view.


Video Answer


1 Answers

If View2 is being used in View1 you could do something like this:

View1:

struct FirstView: View {
    @State var count = 0
    var body: some View {
        VStack{
            Text("\(self.count)")
            Button(action:
                {self.count = self.count-10})
            {
                Text("-")
            }
            SecondView(count: self.$count)
        }
    }
}

And View2:

struct SecondView: View {
    @Binding var count: Int
    var body: some View {
        Button(action: {self.count = 0}) {
            Text("Reset")
        }
    }
}

Edit

If they are completely different views and need single source of truth you could use an observableObject/EnvironmentVariables. The best way would be to add the environment variable to the ContentView where it's first defined in the SceneDelegate

ContentView().environmentObject(SourceOfTruth())

Here is SourceOfTruth:

class SourceOfTruth: ObservableObject{
    @Published var count = 0
}

Then you could use EnvironmentObjects to the other views: Here is ContentView:

struct ContentView: View {
    @EnvironmentObject var truth: SourceOfTruth
    var body: some View {
        VStack {
            FirstView()
            SecondView()
        }
    }
}

Here is FirstView:

struct FirstView: View {
    @EnvironmentObject var truth: SourceOfTruth
    var body: some View {
       VStack{
        Text("\(self.truth.count)")
           Button(action:
            {self.truth.count = self.truth.count-10})
           {
               Text("-")
           }
       }
    }
}

Here is SecondView:

struct SecondView: View {
    @EnvironmentObject var truth: SourceOfTruth
    var body: some View {
        Button(action: {self.truth.count = 0}) {
            Text("Reset")
        }
    }
}
like image 167
39fredy Avatar answered Oct 03 '22 00:10

39fredy