Multiple Sheet (isPresented :) funktioniert in SwiftUI nicht


21

Ich habe diese ContentView mit zwei verschiedenen modalen Ansichten, daher verwende ich sie sheet(isPresented:)für beide, aber anscheinend wird nur die letzte angezeigt . Wie könnte ich dieses Problem lösen? Oder ist es nicht möglich, mehrere Blätter in einer Ansicht in SwiftUI zu verwenden?

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

Der obige Code wird ohne Warnungen kompiliert (Xcode 11.2.1).


Sie können nur ein Blatt haben. Diese Lösung zeigt, wie Sie verschiedene Warnungen erhalten, die Ihrer Situation ähnlich sind und wahrscheinlich leicht wiederverwendet werden können. Stackoverflow.com/questions/58737767/…
Andrew

Antworten:


25

Bitte versuchen Sie es mit dem folgenden Code

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
Diese Lösung ist sinnvoll und kann skaliert werden, danke!
Turing getestet

Versuchte diesen Code mit der switch-Anweisung anstelle von if ... else und bekam den Fehler "Closure mit Kontrollflussanweisung kann nicht mit dem Funktions-Builder 'ViewBuilder' verwendet werden", der verwirrend war, weil nicht if ... else ist Kontrollfluss?
Aaron Surrain

Vielen Dank! Diese Lösung funktioniert
Adelmaer

Ihre SheetViews haben den gleichen Typ: Text, wie wäre es mit einem anderen Typ? Soweit ich sehe, funktioniert es nicht.
Quang Hà

@ QuangHà dafür musst du mit einem anderen Weg machen. oder Sie können zwei oder mehr SheetViews als unterschiedliche Vorgehensweise verwenden
Rohit Makwana

11

Ihr Fall kann wie folgt gelöst werden (getestet mit 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)
    }
}

Ich habe einen Alarm, aber mehrere Bool, der falsch ist, aber einmal wahr (außerhalb des Körpers). Dann möchte ich, dass mein Alarm weiß, welcher Bool wahr ist, und einen bestimmten Alarm anzeigt
Dewan

6

Kann das Blatt auch zu einer leeren Ansicht im Hintergrund der Ansicht hinzufügen. Dies kann mehrmals durchgeführt werden:

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

3

Sie können dies einfach erreichen, indem Sie die Schaltfläche und die .sheet-Aufrufe zusammenfassen. Wenn Sie einen führenden und einen nachfolgenden haben, ist das so einfach. Wenn Sie jedoch mehrere Navigationsleistenelemente entweder im führenden oder im hinteren Bereich haben, müssen Sie diese in einen HStack einschließen und jede Schaltfläche mit ihrem Blattaufruf in einen VStack einschließen.

Hier ist ein Beispiel für zwei nachfolgende Schaltflächen:

            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

Zusätzlich zu Rohit Makwanas Antwort fand ich eine Möglichkeit, den Blattinhalt in eine Funktion zu extrahieren, da es dem Compiler schwer fiel, meinen Giganten zu überprüfen View.

extension YourView {
    enum Sheet {
        case a, b
    }

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

Sie können es folgendermaßen verwenden:

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

Es macht den Code sauberer und entlastet auch Ihren Compiler.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.