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

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

cayZ
quelle