SwiftUI:重置TabView

4
我有一个带有两个选项卡的TabView在一个SwiftUI生命周期应用程序中,其中一个选项卡具有复杂的视图结构:NavigationView,其内部有许多子视图,例如:NavigationLink和它们的DestinationView分散在多个级别的视图树中,每个子视图本身都是另一个视图层次结构,具有sheet和/或其他DestinationView。在这个层次结构的某个位置,我想要将TabView重置为其最初状态,即显示第一个视图,以便用户可以在该状态下重新开始他们的旅程,就像他们第一次打开应用程序那样,因此很难追踪isActiveisPresented绑定来弹出或解除视图和表格。
我考虑将TabView包装在另一个视图RootView中,试图找到一种重新创建TabView的简单方法或类似于刷新/重置 TabView的方式,但无法找到如何实现的线索。
以下是我的代码片段:
@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            RootView()
        }
    }
}

struct RootView: View {
    var body: some View {
        ContentView()
    }
}

struct ContentView: View {
    var body: some View {
        TabView { // <-- I need to reset it to its original state
           View1() // <---- this view has complex view hierarchy
            .tabItem {
                Text("Home")
                
            }.tag(0)
            
            View2()
            .tabItem {
                Text("Settings")
            }.tag(1)
        }
    }
}

p.s.我不想做“将视图弹出到根视图”的操作,因为当有许多活动的NavigationLink目标时,用户可能会打开其中一个sheet并在sheet中开始新的导航旅程。

****** 更新 ******

我创建了一个新的Environment值来保存一个布尔值,该值应指示TabView是否应重置,我跟踪每个视图中的isPresentedisActive状态变量,并在该环境值设置为true后将它们重置,就像这样:

struct ResetTabView: EnvironmentKey {
static var defaultValue: Binding<ResetTabObservable> = .constant(ResetTabObservable())
 }
 extension EnvironmentValues {
var resetTabView: Binding<ResetTabObservable> {
    get { self[ResetTabView.self] }
    set { self[ResetTabView.self] = newValue }
   }
 }

 class ResetTabObservable: ObservableObject {
    @Published var newValue = false
}

在每个将呈现表格或推出新视图的视图中,我都添加了类似于以下内容的代码:
struct View3: View {
    @State var showSheet = false
    @Environment(\.resetTabView) var reset
    
    var body: some View {
        Text("This is view 3")
        Button(action: {
            showSheet = true
        }, label: {
            Text("show view 4")
        })
        .sheet(isPresented: $showSheet) {
            View4()
        }
        .onReceive(reset.$newValue.wrappedValue, perform: { val in
            if val == true {
                showSheet = false
            }
        })
    }
}

在最后一个视图中(将重置TabView),我会像这样切换Environment的值:

struct View5: View {
    @Environment(\.resetTabView) var reset
    
    var body: some View {
        VStack {
            Text("This is view 5")
            Button(action: {
                reset.newValue.wrappedValue = true
            }, label: {
                Text("reset tab view")
            })
        }
    }
}

这导致了观点被尴尬地驳回:

在此输入图片描述


这个回答解决了你的问题吗?https://dev59.com/XcDqa4cB1Zd3GeqPYzpq#67015765(请参见关于*重置到根*的位置) - Asperi
不是我想要的,我在上面的问题中添加了一个P.S.,我不想要“解雇或弹出根视图”。 - JAHelia
1个回答

1
我为此所做的是,将所有演示绑定存储在@SceneStorage("key")中(而不是@State),这样它们不仅尊重状态恢复!而且你还可以通过使用相同的键轻松地在整个应用程序中访问它们。 这篇文章提供了一个很好的例子,说明了如何在iPad上从选项卡切换到侧边栏视图。
我在我的应用程序中使用了这个功能,因此如果我有一个需要取消多个演示的按钮或其他东西,它可以读取所有这些值并将它们重置回所需的值,而无需传递大量绑定。

这不会将大量打开的页面重置为第一个标签页视图,我想实现这一点的最佳方法是创建一个全新的RootView,其中包含一个新的TabView - JAHelia
如果对于这些演示文稿的每一个都有一个SceneStorage,那么在您的按钮中,您可以将它们全部重置为默认状态。(是的,您需要通过显式设置所有这些) - Matthaus Woolard

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