繁体   English   中英

SwiftUI 当 isPresented 值从闭包更改时不会关闭

[英]SwiftUI sheet not dismissing when isPresented value changes from a closure

我有一个工作表视图,当用户单击一个按钮时显示,如下面的父视图所示:

struct ViewWithSheet: View {
    @State var showingSheetView: Bool = false
    @EnvironmetObject var store: DataStore()

    var body: some View {
        NavigationView() {
            ZStack {
               Button(action: { self.showingSheetView = true }) {
                   Text("Show sheet view")
               }
            }
            .navigationBarHidden(true)
            .navigationBarTitle("")
            .sheet(isPresented: $showingSheetView) {
                SheetView(showingSheetView: self.$showingSheetView).environmentObject(self.dataStore)
            }
        }
    }
}

在工作表视图中,当用户单击另一个按钮时,具有完成处理程序的商店会执行一个操作。 完成处理程序返回一个 object 值,如果该值存在,则应关闭 SheetView。

struct SheetView: View {

    @Binding var showingSheetView: Bool

    @EnvironmentObject var store: DataStore()

    //@Environment(\.presentationMode) private var presentationMode

    func create() {
        store.createObject() { object, error in 
           if let _ = object {
               self.showingSheetView = false
               // self.presentationMode.wrappedValue.dismiss()
           }
        }
    }

    var body: some View {
        VStack {
            VStack {
                HStack {
                    Button(action: { self.showingSheetView = false }) {
                        Text("Cancel")
                    }
                    
                    Spacer()
                    
                    Spacer()
                    
                    Button(action: { self.create() }) {
                        Text("Add")
                    }
                }
                .padding()
            }
        }
    }
}

但是,在 create() function 中,一旦商店返回值并将showingSheetView 设置为false,工作表视图不会按预期关闭。 我也尝试过使用 PresentationMode 来关闭工作表,但这似乎也不起作用。

我发现了我的问题,由于我的整体应用程序包装视图中的条件,工作表没有被取消,我有一个 if 语句将在应用程序启动时显示加载视图,但是,在我的 DataStore 中,我将它设置为在每个function 调用它执行。 当该值更改时,我的工作表视图后面的视图堆栈将重新呈现 LoadingView,然后一旦获取变量再次更改,我的 TabView 将重新呈现。 这使得工作表视图不可关闭。 这是我的 AppView 的示例:

struct AppView: View {

    @State private var fetchMessage: String = ""

    @EnvironmentObject var store: DataStore()

    func initializeApp() {
        self.fetchMessage = "Getting App Data"
        store.getData() { object, error in 
            if let error = error {
                self.fetchMessage = error.localizedDescription
            }

            self.fetchMessage = ""
        }
    }

    var body: some View {
        Group {
            ZStack {
                //this is where my issue was occurring
                if(!store.fetching) {
                    TabView {
                        Tab1().tabItem {
                            Image(systemName: "tab-1")
                            Text("Tab1")
                        }

                        Tab2().tabItem {
                            Image(systemName: "tab-2")
                            Text("Tab2")
                        }

                        //Tab 3 contained my ViewWithSheet() and SheetView()
                        Tab3().tabItem {
                            Image(systemName: "tab-3")
                            Text("Tab3")
                        }
                    }
                } else {
                    LoadingView(loadingMessage: $fetchMessage)
                }
            }
        }.onAppear(perform: initializeApp)
    }
}

为了解决我的问题,我在我的 DataStore 中添加了另一个名为 initializing 的变量,我用它在我的应用程序中的 first.onAppear 事件上呈现加载屏幕或实际应用程序视图。 下面是我更新的 AppView 的示例:

struct AppView: View {

    @State private var fetchMessage: String = ""

    @EnvironmentObject var store: DataStore()

    func initializeApp() {
        self.fetchMessage = "Getting App Data"
        store.getData() { object, error in 
            if let error = error {
                self.fetchMessage = error.localizedDescription
            }

            self.fetchMessage = ""
            //set the value to false once I'm done getting my app's initial data.
            self.store.initializing = false
        }
    }

    var body: some View {
        Group {
            ZStack {
                //now using initializing instead
                if(!store.initializing) {
                    TabView {
                        Tab1().tabItem {
                            Image(systemName: "tab-1")
                            Text("Tab1")
                        }

                        Tab2().tabItem {
                            Image(systemName: "tab-2")
                            Text("Tab2")
                        }

                        //Tab 3 contained my ViewWithSheet() and SheetView()
                        Tab3().tabItem {
                            Image(systemName: "tab-3")
                            Text("Tab3")
                        }
                    }
                } else {
                    LoadingView(loadingMessage: $fetchMessage)
                }
            }
        }.onAppear(perform: initializeApp)
    }
}

尝试在主队列上显式执行此操作

func create() {
    store.createObject() { object, error in 
       if let _ = object {
           DispatchQueue.main.async {
              self.showingSheetView = false
           }
       }
       // think also about feedback on else case as well !!
    }
}

想看看对我有用的东西吗? 免责声明:可能不适合你,我不一定推荐它。 但也许它会帮助一个紧要关头的人。

如果您添加NavigationLink并保留您的fullScreenCover ,那么全屏封面将能够像您期望的那样自行关闭。

为什么将 NavigationLink 添加到视图时会发生这种情况? 我不知道。 我的猜测是它在某处创建了额外的参考。

将此添加到您的body中,并保持您的工作表原样:

NavigationLink(destination: YOURVIEW().environmentObjects(), isActive: $showingSheetView) {}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM