以编程方式在SwiftUI中切换到另一个选项卡

36

我正在尝试用SwiftUI实现这样一个功能:当你在一个选项卡上按下按钮后,它会切换到另一个选项卡。如果是在UIKit中,我会这样做:

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

但是在SwiftUI中有没有实现这个功能的等价方法?

2个回答

68

您只需要更新一个负责选择的@State变量。但是,如果您想从子视图中进行操作,可以将其作为@Binding变量传递:

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")
        }
    }
}

如果我们正在使用viewModel呢? - Erkam KUCET
2
如果您想从非常深的视图切换选项卡怎么办?这是一个非常简单的例子。 - Javier Calatrava Llavería
@JavierCalatravaLlavería 这个解决方案可能会对您有所帮助:https://dev59.com/FlEG5IYBdhLWcg3wcuH2#65801058 - pawello2222
@ErkamKUCET,请在您的视图模型中创建一个“Published”变量,然后执行相同的操作。 - cole

3
如果您想从更深入的视图切换,您可能会喜欢使用@AppStorage或@ScreenStorage来保存所选选项卡。
这可能看起来像:
@SceneStorage("selectedView") var selectedView: String?
    
    var body: some View {
        TabView (selection: $selectedView){
            NavigationView {
                TimerView()
            }
            .tag(TimerView.tag)
            .tabItem {
                Image(systemName: "stopwatch.fill")
                Text("Timer")
            }...

然后,在更深入的视图中的任何地方:

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

TimerView.tag在示例中只是常量,以避免在整个应用程序中使用字符串:

static let tag: String? = "Timer"

一旦您更新@SceneStorage值,SwiftUI将处理选项卡切换,并保存应用中最后打开的选项卡。


2
我认为这个解决方案有些过度,只需使用绑定(Binding)来实现“更深层次”的视图即可。如果您不需要将当前页面保存到UserDefaults中,那么为什么要使用它呢? - Dris
1
你说得没错,绑定也可以实现这个功能,但是你想要将选中的标签页保留在UserDefaults中,在不同的会话之间使用。下次打开应用程序时,你会打开相同的标签页。 - Aivars
这种方法似乎在后续版本中无法正常工作。我使用的是 Xcode 15.0 beta 5,在按下按钮时会导致 @main 崩溃,但调试窗口没有显示任何错误。有什么想法吗? - Edward Hasted

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接