TabView selection resets to first tab on sheet presentation
Asked Answered
C

2

8

Update:

Thanks to Harshil & Sumit for pointing me out that I was simply too dumb to realize that I was using id() instead of tag(). If there is anything you can learn from this question, it is this:

When you work alone on a project, you tend to go blind. You don't see your own mistakes. Do code reviews. Ask friends and colleagues to look over it. It's a great idea. ;)

Original Question:

In my SwiftUI project I am using a TabView with a $selection Binding for being able to switch tabs programmatically.

The problem is: When I present a sheet on, for example, the second view contained in the TabView the selection is reset to the first tab.

For me this seems like a SwiftUI bug - but is there a workaround?

Below you find a working example that demonstrates the behaviour. (Tested with Xcode 12.4)

How to test: Go to the second tab, tap the button "Two" and you will see that you get back to the first tab. As soon as you remove the selection property from the TabView this does not happen any more.

Cheers Orlando 🍻

enum TabPosition: Hashable {
    case one
    case two
    case three
}

struct RootView: View {
    
    @State private var selection: TabPosition = .one
    
    var body: some View {
        TabView(selection: $selection) {
            One()
                .tabItem { Label("One", systemImage: "1.circle") }
                .id(TabPosition.one)
            Two()
                .tabItem { Label("Two", systemImage: "2.circle") }
                .id(TabPosition.two)
            Three()
                .tabItem { Label("Three", systemImage: "3.circle") }
                .id(TabPosition.three)
        }
    }
}


struct One: View {
    var body: some View {
        Text("One").padding()
    }
}

struct Two: View {
    
    @State var isPresented = false
    
    var body: some View {
        Button("Two") { isPresented.toggle() }
        .sheet(isPresented: $isPresented, content: {
            Three()
        })
    }
}

struct Three: View {
    var body: some View {
        Text("Three").padding()
    }
}

Coincident answered 27/3, 2021 at 20:18 Comment(0)
A
4

Use .tag() like this:

struct ContentView: View {
    @State private var selection = 1
    var body: some View {
        TabView(selection: $selection) {
            One()
                .tabItem { Label("One", systemImage: "1.circle") }
                .tag(1)
            Two()
                .tabItem { Label("Two", systemImage: "2.circle") }
                .tag(2)
            Three()
                .tabItem { Label("Three", systemImage: "3.circle") }
                .tag(3)
        }
    }
}
Archery answered 27/3, 2021 at 21:2 Comment(0)
M
1

Insted of id .id(TabPosition.one) assign tag like this .tag(TabPosition.one)

Mccallion answered 27/3, 2021 at 21:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.