web-dev-qa-db-ja.com

複数のシート(isPresented :)がSwiftUIで機能しない

このContentViewには2つの異なるモーダルビューがあるので、両方にsheet(isPresented:)を使用していますが、最後の1つしか表示されないようです。この問題を解決するにはどうすればよいですか?または、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!")
            }
        }
    }
}

上記のコードは警告なしにコンパイルされます(Xcode 11.2.1)。

19
turingtested

以下のコードを試してください

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

次の方法で解決できる場合があります(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)
    }
}
8
Asperi

ビューの背景に配置されたEmptyViewにシートを追加することもできます。これは複数回行うことができます:

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

これは、ボタンと.sheet呼び出しをグループ化するだけで実現できます。あなたが1つの先行と1つの後続がある場合、それはとても簡単です。ただし、先頭または末尾に複数のnavigationbaritemsがある場合は、それらをHStackでラップし、各ボタンをシート呼び出しでVStackでラップする必要があります。

次に、2つの末尾ボタンの例を示します。

            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
2
user2698617

Rohit Makwanaの回答 に加えて、コンパイラーが巨大なViewの型チェックに苦労していたため、シートの内容を関数に抽出する方法を見つけました。

extension YourView {
    enum Sheet {
        case a, b
    }

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

次のように使用できます。

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

これにより、コードがよりクリーンになり、コンパイラのストレスも軽減されます。

0
cayZ