SwiftUI'da birden fazla sayfa (isPresented :) çalışmıyor


21

Ben bu ContentView iki farklı mod görünümleri var, bu yüzden sheet(isPresented:)her ikisi için kullanıyorum , ama sadece sonuncusu gibi görünüyor gibi. Bu sorunu nasıl çözebilirim? Veya SwiftUI'de bir görünümde birden çok sayfa kullanmak mümkün değil mi?

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

Yukarıdaki kod uyarısız derlenir (Xcode 11.2.1).


Yalnızca bir sayfanız olabilir. Bu çözüm, durumunuza benzer ve muhtemelen kolayca yeniden yerleştirilebilecek farklı uyarıların nasıl alınacağını gösterir stackoverflow.com/questions/58737767/…
Andrew

Yanıtlar:


25

Lütfen aşağıdaki kodu deneyin

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
Bu çözüm mantıklı ve ölçeklenebilir, teşekkürler!
19:25

Bu kodu if ... else yerine switch deyimiyle denedim ve "Kontrol akışı deyimini içeren kapatma," ViewBuilder "işlev oluşturucu ile kullanılamaz" gibi şaşırtıcıydı çünkü kontrol değil mi?
Aaron Surrain

Teşekkürler! Bu çözüm çalışıyor
Adelmaer

SheetView'larınız aynı türe sahip: Metin, farklı tipe ne dersiniz? Gördüğüm kadarıyla çalışmıyor.
Quang Hà

@ QuangHà bunun için başka bir yolla yapmanız gerekiyor. veya farklı bir yaklaşım olarak iki veya daha fazla SheetView alabilirsin
Rohit Makwana

11

Durumunuz aşağıdakilerle çözülebilir (Xcode 11.2 ile test edilmiştir)

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

Bir uyarı var ama yanlış ama bir kez doğru olan birden fazla Bool var (vücudun dışında) sonra uyarımın hangi Bool'un doğru olduğunu bilmesini ve belirli bir Uyarıyı göstermesini istiyorum
Dewan

6

Sayfayı, görünümün arka planına yerleştirilen bir EmptyView öğesine de ekleyebilir. Bu, birkaç kez yapılabilir:

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

3

Bunu, düğmeyi ve .sheet çağrılarını birlikte gruplandırarak gerçekleştirebilirsiniz. Eğer bir lider ve bir takip varsa bu kadar basit. Ancak, önde veya arkada birden fazla gezinme çubuğu öğeniz varsa, bunları bir HStack'a sarmanız ve ayrıca her düğmeyi bir VStack'ta sayfa çağrısı ile sarmanız gerekir.

Aşağıda, sondaki iki düğmeye bir örnek verilmiştir:

            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

Rohit Makwana'nın cevabına ek olarak , sayfa içeriğini bir işleve çıkarmanın bir yolunu buldum çünkü derleyici devimi kontrol etmekte zorlanıyordu View.

extension YourView {
    enum Sheet {
        case a, b
    }

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

Bu şekilde kullanabilirsiniz:

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

Kodu daha temiz hale getirir ve ayrıca derleyicinizin stresini azaltır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.