35

I'm trying to implement in SwiftUI where you press a button in a view on one tab, it changes to another tab. I would do with UIKit:

if [condition...button pressed] {
    self.tabBarController!.selectedIndex = 2
}

But is there an equivalent way to achieve this in SwiftUI?

pawello2222
  • 46,897
  • 22
  • 145
  • 209
guckmalmensch
  • 973
  • 2
  • 9
  • 22

2 Answers2

65

You just need to update a @State variable responsible for the selection. But if you want to do it from a child View you can pass it as a @Binding variable:

struct ContentView: View {
    @State private var tabSelection = 1
    
    var body: some View {
        TabView(selection: $tabSelection) {
            FirstView(tabSelection: $tabSelection)
                .tabItem {
                    Text("Tab 1")
                }
                .tag(1)
            Text("tab 2")
                .tabItem {
                    Text("Tab 2")
                }
                .tag(2)
        }
    }
}
struct FirstView: View {
    @Binding var tabSelection: Int
    var body: some View {
        Button(action: {
            self.tabSelection = 2
        }) {
            Text("Change to tab 2")
        }
    }
}
pawello2222
  • 46,897
  • 22
  • 145
  • 209
3

If you like to switch from deeper views you may like to use @AppStorage or @SceenStorage to save the selected tab.

that could look like:

@SceneStorage("selectedView") var selectedView: String?
    
    var body: some View {
        TabView (selection: $selectedView){
            NavigationView {
                TimerView()
            }
            .tag(TimerView.tag)
            .tabItem {
                Image(systemName: "stopwatch.fill")
                Text("Timer")
            }...

And then anywhere in deeper views:

 Button(action: {
                selectedView = TimerView.tag
                    }) {
                        Text("Switch Tab")
                      
                    }

TimerView.tag in example is just constant to do not use strings across the app:

static let tag: String? = "Timer"

SwiftUI will take care of Tab switching as soon as you will update @SceneStorage value and it will save last opened tab in the app as well.

Aivars
  • 161
  • 9
  • 2
    I think this solution is overkill, simply just use Binding for 'deeper' view. If you don't need to save the current page into UserDefaults, why would you use it? – Dris Apr 26 '22 at 08:35
  • 1
    You are right about the binding that would work as well, but you would like to keep the selected tab in UserDefaults to use between sessions. You would open the same tab on the next opening of the app. – Aivars Feb 22 '23 at 12:38
  • This approach appears not to be working in later versions. Am on Xcode 15.0 beta 5 and when you press the button is crashes to @main with no errors in the debug screen. Any thoughts? – Edward Hasted Aug 15 '23 at 13:09