SwiftUI에서 여러 시트 (isPresented :)가 작동하지 않습니다


21

이 ContentView에는 두 개의 다른 모달 뷰가 있으므로 두 가지 sheet(isPresented:)모두에 사용하고 있지만 마지막 뷰 만 표시되는 것처럼 보입니다. 이 문제를 어떻게 해결할 수 있습니까? 아니면 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).


한 장만 가질 수 있습니다. 이 솔루션은 상황과 유사하고 다른 목적으로 쉽게 다른 경고를 사용하는 방법을 보여줍니다. stackoverflow.com/questions/58737767/…
Andrew

답변:


25

아래 코드를 시도하십시오

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
이 솔루션은 이해하기 쉽고 확장 가능합니다.
turingtest에 의해

if ... else 대신 switch 문을 사용하여이 코드를 시도하고 "제어 흐름 문이 포함 된 클로저는 함수 작성기 'ViewBuilder'와 함께 사용할 수 없습니다."라는 오류가 발생합니다.
Aaron Surrain

감사! 이 솔루션은 작동합니다
Adelmaer

SheetView는 같은 유형입니다. 텍스트, 다른 유형은 어떻습니까? 내가 아는 한 작동하지 않습니다.
Quang Hà

@ QuangHà 당신은 다른 방법으로해야합니다. 또는 다른 접근 방식으로 둘 이상의 SheetView를 사용할 수 있습니다
Rohit Makwana

11

당신은 사건을 다음과 같이 해결할 수 있습니다 (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)
    }
}

하나의 경고가 있지만 여러 개의 Bool이 거짓이지만 한 번만 사실 인 경우 (본체 외부) Boal이 어느 Bool이 사실인지 알고 특정 경고를 표시하기를 원합니다
Dewan

6

뷰의 배경에 배치 된 EmptyView에 시트를 추가 할 수도 있습니다. 여러 번 수행 할 수 있습니다.

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

3

버튼과 .sheet 호출을 그룹화하여 간단히 수행 할 수 있습니다. 하나의 선행과 하나의 후행이 있으면 간단합니다. 그러나 선행 또는 후행에 여러 탐색 표시 줄 항목이있는 경우이를 HStack으로 랩핑하고 각 단추를 시트 호출로 VStack으로 랩핑해야합니다.

두 개의 후행 버튼의 예는 다음과 같습니다.

            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의 답변 외에도 컴파일러가 거대한 형식 검사에 어려움을 겪어 시트 내용을 함수로 추출하는 방법을 찾았습니다 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)

코드를 더 깨끗하게 만들고 컴파일러의 스트레스를 덜어줍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.