从封闭中更改isPresented值后,SwiftUI工作表不会关闭

时间:2020-07-20 01:58:16

标签: ios swift xcode swiftui ios13

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

    # function to perform the fit
    def _fit_rti_curve(data, data_rti, fit, loc=False):
        fit_func, linearize, find_init_params = _get_fit_functions(fit)
        # remove nans
        x, y = _filter_nodata(data_rti, data)
        # remove outliers
        x, y = _filter_for_outliers(x, y, linearize=linearize)

        # find a first guess for maximum achieveable value
        yscale = np.max(y) * 1.05
        # find a first guess for the other parameters
        # here loc can be manually passed if you have a good estimation
        init_parms = find_init_params(x, y, yscale, loc=loc, linearize=linearize)
        # fit the curve and return parameters
        parms = curve_fit(fit_func, x, y, p0=init_parms, maxfev=10000)
        parms = parms[0]
        return parms

    # shell around _fit_rti_curve
    def find_rti_func_parms(data, rti, fit):
        # sort and fit highest n values
        top_data = np.sort(data)
        top_data = top_data[-len(rti):]

        # convert to float64 if needed
        top_data = top_data.astype(np.float64)
        rti = rti.astype(np.float64)

        # run the fit
        parms = _fit_rti_curve(top_data, rti, fit, loc=0) #TODO maybe add function to allow a free loc
        return parms


    # call for the apply_ufunc
    # `fit` is a string that defines the distribution type
    # `rti` is an array for the x values
    parms_data = xr.apply_ufunc(
        find_rti_func_parms,
        xr_obj,
        input_core_dims=[['time']],
        output_core_dims=[[fit + ' parameters']],
        output_sizes = {fit + ' parameters': len(signature(fit_func).parameters) - 1},
        vectorize=True,
        kwargs={'rti':return_time_interval, 'fit':fit},
        dask='parallelized',
        output_dtypes=['float64']
    )

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

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

但是,在create()函数中,一旦商店返回值并将showingSheetView设置为false,则工作表视图将不会按预期方式消失。我也尝试过使用presentationMode来消除工作表,但这似乎也不起作用。

3 个答案:

答案 0 :(得分:2)

我发现了我的问题,由于整个应用程序包装视图中的条件,表格没有被取消,我有一个if语句将显示应用程序启动时的加载视图,但是,在我的DataStore中,我正在设置获取执行的每个函数调用上的变量。当该值更改时,工作表视图后面的视图堆栈将重新呈现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中添加了另一个变量称为Initialization,该变量用于在应用程序中的第一个.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)
    }
}

答案 1 :(得分:1)

尝试在主队列上明确执行此操作

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 !!
    }
}

答案 2 :(得分:0)

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

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

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

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

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