5

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

iruleee
  • 51
  • 1
  • 2
  • Can you explain how the views relate to one another ? Is `View2` going to be used in `View1` etc. or are you looking for one global source of truth ? – 39fredy Oct 18 '19 at 16:21
  • Thanks for your reply, looking for one global source of truth. Someway I can change the value of `count` in all swift files in the app. – iruleee Oct 18 '19 at 16:43

1 Answers1

5

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")
        }
    }
}
39fredy
  • 1,923
  • 2
  • 21
  • 40
  • Thanks for your help, but View 2 is in a separate view – iruleee Oct 18 '19 at 16:42
  • Can you give us a little more context about the view hierarchy (ie how do the views relate to one another?) You might be able to use an observableObject. – 39fredy Oct 18 '19 at 16:44
  • Let me explain the project. I'm trying to build a sample WatchOS app for learning swiftui. In the first view there are two buttons on pressing one button the value increments and the changes take place. The second button subtracts and the value reduces by one. On View 2, there is a reset button that when pressed should change the variable to 0. Everything in view 1 works perfectly. but I cannot get the variable to be called to reset the value in view one. Hope that clears the problem a little. Thanks for all your help – iruleee Oct 18 '19 at 17:14
  • I have edited the answer, hope that helps! The main question I have is how do you swift to view2 from view1? – 39fredy Oct 18 '19 at 17:31
  • Thanks a lot. Environment object on the first view works perfectly but as soon as i put `self.truth.count = 0` in button action on view 2 it crashes the app on start with the error `Fatal error: No observable object of type SourceOfTruth.Type found` – iruleee Oct 18 '19 at 20:34
  • Any chance you could post images of your code or something. I need to understand how view 1 and view 2 are related. Meaning how do you get from view one to view two. – 39fredy Oct 18 '19 at 23:52
  • 1
    This was very helpful. I was trying to pass one variable from a primary view to another view. The key that helped me was making sure that @ State was declared in the primary view, and @ Binding in the subview. – FontFamily Dec 07 '20 at 17:21