Foglio multiplo (isPresented :) non funziona in SwiftUI


21

Ho questo ContentView con due diverse viste modali, quindi sto usando sheet(isPresented:)per entrambi, ma sembra che solo l'ultimo sia presentato. Come potrei risolvere questo problema? Oppure non è possibile utilizzare più fogli su una vista in 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!")
            }
        }
    }
}

Il codice sopra riportato viene compilato senza avvisi (Xcode 11.2.1).


Puoi avere solo un foglio. Questa soluzione mostra come avere diversi avvisi che sono simili alla tua situazione e che potrebbero essere facilmente riproposti stackoverflow.com/questions/58737767/…
Andrew

Risposte:


27

Si prega di provare sotto il codice

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
Questa soluzione ha senso e può ridimensionarsi, grazie!
Turingtest del

Ho provato questo codice con l'istruzione switch invece di if ... else e ho ricevuto l'errore "L'istruzione di chiusura contenente il flusso di controllo non può essere utilizzata con il costruttore di funzioni 'ViewBuilder'" che era sconcertante perché non lo è se ... altrimenti è flusso di controllo?
Aaron Surrain,

Grazie! Questa soluzione funziona
Adelmaer il

Le tue SheetView hanno lo stesso tipo: testo, che ne dici di un tipo diverso? Per quanto vedo, non funziona.
Quang Hà

@ QuangHà per questo devi fare un altro modo. oppure puoi prendere due o più SheetView per l'approccio diverso che hai
Rohit Makwana,

11

Il tuo caso può essere risolto nel modo seguente (testato 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)
    }
}

Ho un avviso ma un Bool multiplo che è falso ma una volta vero (al di fuori del corpo), quindi voglio che il mio avviso sappia quale Bool è vero e mostri un certo avviso
Dewan

6

È inoltre possibile aggiungere il foglio a un EmptyView posizionato sullo sfondo della vista. Questo può essere fatto più volte:

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

3

Puoi farlo semplicemente raggruppando il pulsante e le chiamate .sheet insieme. Se ne hai uno in testa e uno in coda è così semplice. Tuttavia, se hai più barre di navigazione sia in testa che in coda, devi avvolgerle in un HStack e anche avvolgere ogni pulsante con la sua chiamata in un VStack.

Ecco un esempio di due pulsanti finali:

            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

Oltre alla risposta di Rohit Makwana , ho trovato un modo per estrarre il contenuto del foglio in una funzione perché il compilatore stava facendo fatica a controllare il mio gigantesco View.

extension YourView {
    enum Sheet {
        case a, b
    }

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

Puoi usarlo in questo modo:

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

Rende il codice più pulito e allevia anche lo stress del compilatore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.