Várias folhas (isPresented :) não funcionam no SwiftUI


21

Eu tenho esse ContentView com duas visualizações modais diferentes, então estou usando sheet(isPresented:)para ambas, mas, como parece, apenas a última é apresentada. Como eu poderia resolver esse problema? Ou não é possível usar várias folhas em uma exibição no 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!")
            }
        }
    }
}

O código acima é compilado sem avisos (Xcode 11.2.1).


Você pode ter apenas uma folha. Esta solução mostra como têm diferentes alertas que é semelhante à sua situação e provavelmente poderia ser facilmente reaproveitado stackoverflow.com/questions/58737767/...
— Andrew

Respostas:


27

Por favor, tente o código abaixo

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

11
Esta solução faz sentido e pode ser dimensionada, obrigado!
— turingtested

Tentei esse código com a instrução switch em vez de if ... else e recebi o erro "O fechamento que contém a instrução de fluxo de controle não pode ser usado com o construtor de funções 'ViewBuilder'", que era desconcertante porque não é se ... else é o fluxo de controle?
— Aaron Surrain 16/01

Obrigado! Esta solução funciona
— Adelmaer 29/01

Seu SheetViews tem o mesmo tipo: Texto, que tal um tipo diferente? Tanto quanto vejo, não está funcionando.
— Quang Hà

@ QuangHà para isso você precisa fazer de outra maneira. ou você pode ter dois ou mais SheetViews como uma abordagem diferente que você tem
— Rohit Makwana

11

Seu caso pode ser resolvido da seguinte forma (testado com o 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)
    }
}

Eu tenho um alerta, mas vários bools que são falsos, mas uma vez verdadeiros (fora do corpo), quero que meu alerta saiba qual bool é verdadeiro e mostre um certo alerta
— Dewan

6

Também pode adicionar a planilha a um EmptyView colocado no plano de fundo da visualização. Isso pode ser feito várias vezes:

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

3

Você pode fazer isso simplesmente agrupando o botão e a chamada .sheet. Se você tem um líder e outro à frente, é simples assim. No entanto, se você tiver vários itens de navegação no início ou no final, precisará agrupá-los em um HStack e também agrupar cada botão com sua chamada de planilha em um VStack.

Aqui está um exemplo de dois botões à direita:

            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

Além da resposta de Rohit Makwana , eu encontrei uma maneira de extrair o conteúdo da planilha para uma função porque o compilador estava com dificuldades para verificar meu gigantesco View.

extension YourView {
    enum Sheet {
        case a, b
    }

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

Você pode usá-lo desta maneira:

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

Isso torna o código mais limpo e também alivia o estresse do seu compilador.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.