I am using a switch statement in a SwiftUI view:
struct OnOffSwitchView: View {
@ObservedObject var vm = ViewModel()
var body: some View {
switch vm.state {
case .on:
OnView(vm: vm)
case .off:
OffView(vm: vm)
}
}
}
@MainActor class ViewModel: ObservableObject {
@Published var state: State = .on
enum State {
case on
case off
}
}
Where the child views are changing the ViewModel state (on and off are the same) such that the switch condition updates, rendering a new view:
struct OnView: View {
@ObservedObject var vm: ViewModel
var body: some View {
VStack {
Text("Welcome to On")
Button { vm.state = .off }
label: { Text("Toggle") }
}
}
}
This works fine in a single view:
But, when nesting in a tab view, changing the state causes the TabView to change tabs:
TabView {
Text("Home Tab")
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
OnOffSwitchView()
.tabItem {
Image(systemName: "switch.2")
Text("Switch")
}
}
Any ideas why this happening? I am unsure if (1) there is a problem with my setup (managing the state change), (2) I am missing something in the TabView, or (3) it's an issue with SwiftUI.
This toy example is available on GitHub Updated with answer.
CodePudding user response:
I think it is a bug, because OnOffSwitchView
should be detected identical (by default properties-based convention)... anyway introducing explicit selection
solves the issue
Tested with Xcode 13.4 / iOS 15.5
struct ContentView: View {
@State private var selection = 0
var body: some View {
TabView(selection: $selection) { // << preserves selected tab !!
Text("Home Tab")
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}.tag(0)
OnOffSwitchView()
.tabItem {
Image(systemName: "switch.2")
Text("Switch")
}.tag(1)
}
}
}
*Note: I would recommend in this case use StateObject
for view model in OnOffSwitchView
.