Beberapa lembar (isPresented :) tidak berfungsi di SwiftUI

21

Saya memiliki ContentView ini dengan dua tampilan modal yang berbeda, jadi saya gunakan sheet(isPresented:)untuk keduanya, tetapi sepertinya hanya yang terakhir yang disajikan. Bagaimana saya bisa mengatasi masalah ini? Atau apakah tidak mungkin untuk menggunakan banyak sheet pada tampilan di 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!")
            }
        }
    }
}

Kode di atas dikompilasi tanpa peringatan (Xcode 11.2.1).

diujicobakan
sumber
Anda hanya dapat memiliki satu lembar. Solusi ini menunjukkan cara memiliki lansiran berbeda yang serupa dengan situasi Anda dan mungkin dapat dengan mudah digunakan kembali stackoverflow.com/questions/58737767/…
Andrew

Jawaban:

27

Silakan coba kode di bawah ini

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
sumber
1
Solusi ini masuk akal dan dapat ditingkatkan, terima kasih!
turingtested
Mencoba kode ini dengan pernyataan switch alih-alih jika ... lain dan mendapat kesalahan "Penutupan yang berisi pernyataan aliran kontrol tidak dapat digunakan dengan pembangun fungsi 'ViewBuilder'" yang membingungkan karena bukankah jika ... apakah aliran kontrol itu?
Aaron Surrain
Terima kasih! Solusi ini Berfungsi
Adelmaer
SheetViews Anda memiliki tipe yang sama: Teks, bagaimana dengan tipe yang berbeda? Sejauh yang saya lihat, itu tidak berfungsi.
Quang Hà
@ QuangHà untuk itu perlu Anda lakukan dengan cara lain. atau Anda dapat mengambil dua atau lebih SheetViews sebagai pendekatan berbeda yang Anda miliki
Rohit Makwana
11

Kasus Anda dapat diselesaikan dengan mengikuti (diuji dengan 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
sumber
Saya memiliki satu Lansiran namun banyak Bool yang salah tetapi sekali benar (di luar tubuh) maka saya ingin Lansiran saya mengetahui Bool mana yang benar dan menampilkan Lansiran tertentu
Dewan
6

Dapat juga menambahkan sheet ke EmptyView yang ditempatkan di latar belakang tampilan. Ini dapat dilakukan beberapa kali:

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

Anda dapat melakukannya hanya dengan mengelompokkan tombol dan panggilan lembar. Jika Anda memiliki satu pimpinan dan satu trailing, sesederhana itu. Namun, jika Anda memiliki beberapa bilah navigasi di bagian depan atau belakang, Anda harus membungkusnya dalam HStack dan juga membungkus setiap tombol dengan panggilan sheet-nya dalam VStack.

Berikut adalah contoh dua tombol tambahan:

            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
sumber
1

Selain jawaban Rohit Makwana , saya menemukan cara untuk mengekstrak konten sheet ke suatu fungsi karena kompiler mengalami kesulitan mengetik-memeriksa raksasa saya View.

extension YourView {
    enum Sheet {
        case a, b
    }

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

Anda dapat menggunakannya dengan cara ini:

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

Itu membuat kode lebih bersih dan juga mengurangi tekanan kompiler Anda.

cayZ
sumber