The problem is that you are always initializing a new view with a Ledger.
@State was meant to change the view on the spot, not re-initialize it.
For example
import SwiftUI struct SwiftUIView: View { @State counter: Int = 0 var body: some View { VStack { Button(action:{ self.counter += 1 }) { Text("Increment") } Text("counter: \(self.counter)") } } }
In the above code you can see a use for state, where the variable and the command that change the variable are both in the same view.
In your example, if what changes the tabs is in the same view then you can use @State and 1 LedgerView but with the @State attached to it.
For example
import SwiftUI struct SwiftUIView: View { @State ledger: LedgerType = 0 var body: some View { VStack { LedgerView(ledger: self.ledger) HStack { Button(action:{ self.ledger = .Account }) { Text("Account") } Button(action:{ self.ledger = .Budget }) { Text("Budget") } } } } } struct LedgerView:View { @EnvironmentObject var shared:SharedObject var ledger:LedgerType var body:some View { Text(ledger.name) } }
Yes you can just remove the @State from your example and it should work fine for you but you lose things such as animations between views.
However, as I understand you are don't have the controls on the same view hence I would recommend using EnvironmentObject the way you are using it. But instead of keeping track of the index, I would keep track of the actual LedgerType chosen. Or you can keep track of both.
If you keep track of the page the ledger on shared then you can do this easily
import SwiftUI struct SwiftUIView: View { @EnvironmentObject var shared:SharedObject var body: some View { VStack { LedgerView(ledger: shared.ledger) } } } struct LedgerView:View { @EnvironmentObject var shared:SharedObject var ledger:LedgerType var body:some View { Text(ledger.name) } }
What you were doing doesn't make sense, because again you want to use @State when you want to change something in the same page. In your example inside LedgerView you are creating a variable @State var ledger:LedgerType but in reality if the value of this variable changes INSIDE this instance, it doesn't mean anything to you. You only care about the change of the ledger value in a different view (such as root or parent view) hence using @State needs to be in the parent/root view.
I hope this makes sense.