4

我在生命周期应用程序TabView中有两个选项卡SwiftUI,其中一个具有复杂的视图结构:NavigationView内部有很多子视图,即:NavigationLinks 和它们DestinationView的 s 分布在视图树的多个级别上,每个子视图在其上own 是另一个带有sheets 和/或 other的视图层次结构DestinationView。在这个层次结构中的某个点,我想将TabView其重置为显示第一个最多视图的原始状态,这样用户就可以在该状态下重新开始他们的旅程,就像他们第一次打开应用程序一样,所以它是有点不可能找到类似isActive&isPresented绑定的东西来弹出或关闭视图和工作表。

我想在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)
        }
    }
}

ps 我不是在寻找“从视图弹出到根视图NavigationLink”,因为当用户可能打开其中一个工作表并在工作表内开始新的导航旅程的许多活动目的地时,这是无法完成的。

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

我创建了一个新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")
            })
        }
    }
}

这导致尴尬地驳回意见:

在此处输入图像描述

4

1 回答 1

1

我为此做的是我使用@SceneStorage("key")(而不是@State)存储我所有的演示绑定,这样它们不仅尊重状态恢复!但是您也可以使用相同的密钥轻松地在整个应用程序中访问它们。这篇文章提供了一个很好的例子,说明了如何在 iPad 上实现从 Tab 到 Sidebar 视图的切换。

我在我的应用程序中使用了它,所以如果我有一个按钮或需要展开许多演示文稿的东西,它可以读取所有这些值并将它们重置回想要的值,而无需传递大量绑定。

于 2021-04-12T05:42:30.880 回答