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

testado
fonte
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!")
                }
            }
        }
    }
}
Rohit Makwana
fonte
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)
    }
}
Asperi
fonte
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))
Tylerc230
fonte
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
user2698617
fonte
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.

cayZ
fonte