多个工作表(isPresented :)在SwiftUI中不起作用


21

我的ContentView具有两个不同的模式视图,因此我都使用sheet(isPresented:)了这两种视图,但似乎只显示了最后一个。我该如何解决这个问题?还是无法在SwiftUI的视图上使用多个图纸?

struct ContentView: View {

    @State private var firstIsPresented = false
    @State private var secondIsPresented = false

    var body: some View {

        NavigationView {
            VStack(spacing: 20) {
                Button("First modal view") {
                    self.firstIsPresented.toggle()
                }
                Button ("Second modal view") {
                    self.secondIsPresented.toggle()
                }
            }
            .navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
            .sheet(isPresented: $firstIsPresented) {
                    Text("First modal view")
            }
            .sheet(isPresented: $secondIsPresented) {
                    Text("Only the second modal view works!")
            }
        }
    }
}

上面的代码编译时没有警告(Xcode 11.2.1)。


您只能有一张纸。该解决方案显示了如何具有与您的情况类似的不同警报,并且可能很容易重新利用 stackoverflow.com/questions/58737767/…–
Andrew

Answers:


25

请尝试以下代码

enum ActiveSheet {
   case first, second
}

struct ContentView: View {

    @State private var showSheet = false
    @State private var activeSheet: ActiveSheet = .first

    var body: some View {

        NavigationView {
            VStack(spacing: 20) {
                Button("First modal view") {
                    self.showSheet = true
                    self.activeSheet = .first
                }
                Button ("Second modal view") {
                    self.showSheet = true
                    self.activeSheet = .second
                }
            }
            .navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
            .sheet(isPresented: $showSheet) {
                if self.activeSheet == .first {
                    Text("First modal view")
                }
                else {
                    Text("Only the second modal view works!")
                }
            }
        }
    }
}

1
此解决方案很有意义,可以扩展,谢谢!
turingtest

使用switch语句而不是if ... else尝试了此代码,并得到了错误消息“无法将包含封闭流的控制流语句与函数构建器'ViewBuilder'一起使用”,这是令人困惑的,因为如果... else不是控制流?
亚伦·苏林

谢谢!此解决方案有效
Adelmaer

您的SheetView具有相同的类型:文本,不同的类型呢?据我所知,它不起作用。
广哈

@QuangHà,您需要使用其他方法。或者您可以采用两种或多种SheetViews作为不同的方法
Rohit Makwana

11

您的情况可以通过以下方法解决(已通过Xcode 11.2测试)

var body: some View {

    NavigationView {
        VStack(spacing: 20) {
            Button("First modal view") {
                self.firstIsPresented.toggle()
            }
            .sheet(isPresented: $firstIsPresented) {
                    Text("First modal view")
            }
            Button ("Second modal view") {
                self.secondIsPresented.toggle()
            }
            .sheet(isPresented: $secondIsPresented) {
                    Text("Only the second modal view works!")
            }
        }
        .navigationBarTitle(Text("Multiple modal view problem"), displayMode: .inline)
    }
}

我有一个警报,但有多个布尔,它是错误的,但一旦为真(在身体外部),那么我想让我的警报知道哪个布尔是真实的,并显示某个警报
Dewan

6

也可以将工作表添加到放置在视图背景中的EmptyView。这可以多次执行:

  .background(EmptyView()
        .sheet(isPresented: isPresented, content: content))

3

您只需将按钮和.sheet调用组合在一起即可完成此操作。如果您有一个领先者和一个落后者,那就很简单。但是,如果在开头或结尾有多个导航项,则需要将它们包装在HStack中,并将每个按钮及其表单调用包装在VStack中。

这是两个尾随按钮的示例:

            trailing:
            HStack {
                VStack {
                    Button(
                        action: {
                            self.showOne.toggle()
                    }
                    ) {
                        Image(systemName: "camera")
                    }
                    .sheet(isPresented: self.$showOne) {
                        OneView().environment(\.managedObjectContext, self.managedObjectContext)
                    }
                }//showOne vstack

                VStack {
                    Button(
                        action: {
                            self.showTwo.toggle()
                    }
                    ) {
                        Image(systemName: "film")
                    }
                    .sheet(isPresented: self.$showTwo) {
                        TwoView().environment(\.managedObjectContext, self.managedObjectContext)
                    }
                }//show two vstack
            }//nav bar button hstack

1

除了Rohit Makwana的答案外,我还找到了一种将工作表内容提取到函数的方法,因为编译器很难检查我的硕大代码View

extension YourView {
    enum Sheet {
        case a, b
    }

    @ViewBuilder func sheetContent() -> some View {
        if activeSheet == .a {
            A()
        } else if activeSheet == .b {
            B()
        }
    }
}

您可以通过以下方式使用它:

.sheet(isPresented: $isSheetPresented, content: sheetContent)

它使代码更整洁,也减轻了编译器的压力。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.