La hoja múltiple (isPresented :) no funciona en SwiftUI

22

Tengo este ContentView con dos vistas modales diferentes, así que lo estoy usando sheet(isPresented:)para ambos, pero parece que solo se presenta el último. ¿Cómo podría resolver este problema? ¿O no es posible usar varias hojas en una vista en 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!")
            }
        }
    }
}

El código anterior se compila sin advertencias (Xcode 11.2.1).

probado
fuente
Solo puedes tener una hoja. Esta solución muestra cómo tener diferentes alertas que es similar a su situación y que probablemente podría reutilizarse fácilmente stackoverflow.com/questions/58737767/…
Andrew

Respuestas:

27

Por favor, intente debajo del código

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
fuente
1
Esta solución tiene sentido y puede escalar, ¡gracias!
probado el
Intenté este código con la instrucción switch en lugar de if ... else y obtuve el error "El cierre que contiene la instrucción de flujo de control no se puede usar con el generador de funciones 'ViewBuilder'", lo cual era desconcertante porque no es si ... ¿si no es el flujo de control?
Aaron Surrain
¡Gracias! Esta solución funciona
Adelmaer
Sus SheetViews tienen el mismo tipo: Texto, ¿qué tal un tipo diferente? Por lo que veo, no está funcionando.
Quang Hà
@ QuangHà para eso tienes que ver de otra manera. o puede tomar dos o más SheetViews como un enfoque diferente que tiene
Rohit Makwana
12

Su caso se puede resolver de la siguiente manera (probado con 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
fuente
Tengo una alerta pero varias Bool que son falsas pero una vez verdaderas (fuera del cuerpo), entonces quiero que mi Alerta sepa cuál es la Bool verdadera y que muestre cierta alerta
Dewan
6

También puede agregar la hoja a un EmptyView colocado en el fondo de la vista. Esto se puede hacer varias veces:

  .background(EmptyView()
        .sheet(isPresented: isPresented, content: content))
Tylerc230
fuente
3

Puede lograr esto simplemente agrupando el botón y las llamadas .sheet juntas. Si tiene uno al principio y otro al final, es así de simple. Sin embargo, si tiene múltiples elementos de barra de navegación en el inicio o al final, debe ajustarlos en un HStack y también ajustar cada botón con su hoja de llamada en un VStack.

Aquí hay un ejemplo de dos botones finales:

            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
usuario2698617
fuente
1

Además de la respuesta de Rohit Makwana , encontré una forma de extraer el contenido de la hoja a una función porque el compilador estaba teniendo dificultades para verificar mi gigantesco View.

extension YourView {
    enum Sheet {
        case a, b
    }

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

Puedes usarlo de esta manera:

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

Hace que el código sea más limpio y también alivia el estrés de su compilador.

cayZ
fuente