หลายแผ่น (isPresented :) ไม่ทำงานใน SwiftUI


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)


คุณสามารถมีหนึ่งแผ่นเท่านั้น โซลูชันนี้แสดงวิธีการแจ้งเตือนที่แตกต่างกันซึ่งคล้ายกับสถานการณ์ของคุณและอาจ repurposed 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
วิธีนี้เหมาะสมและสามารถปรับขนาดได้ขอบคุณ!
turingtested

ลองใช้รหัสนี้ด้วยคำสั่ง switch แทนที่จะเป็น ... else และได้รับข้อผิดพลาด "การปิดคำสั่งควบคุมการไหลที่มีอยู่ไม่สามารถใช้กับตัวสร้างฟังก์ชั่น 'ViewBuilder'" ซึ่งยุ่งเหยิงเพราะไม่ได้ถ้า ... เป็นกระบวนการควบคุม
แอรอนเซอร์เร

ขอบคุณ! วิธีนี้ใช้ได้ผล
Adelmaer

SheetViews ของคุณมีประเภทเดียวกัน: ข้อความแล้วประเภทที่แตกต่างกันอย่างไร เท่าที่ฉันเห็นมันไม่ทำงาน
Quang Hà

@ QuangHàสำหรับสิ่งที่คุณต้องทำด้วยวิธีอื่น หรือคุณสามารถใช้มุมมองชีทสองภาพขึ้นไปเป็นแนวทางที่แตกต่างออกไป
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 ที่เป็นเท็จ แต่เมื่อจริง (นอกร่างกาย) จากนั้นฉันต้องการให้การแจ้งเตือนของฉันรู้ว่า Bool ใดที่เป็นความจริงและเพื่อแสดงการแจ้งเตือนบางอย่าง
Dewan

6

ยังสามารถเพิ่มแผ่นงานไปยัง EmptyView ที่วางไว้ในพื้นหลังของมุมมอง สามารถทำได้หลายครั้ง:

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

3

คุณสามารถทำสิ่งนี้ได้อย่างง่ายดายโดยการจัดกลุ่มปุ่มและ. ชีตเรียกเข้าด้วยกัน หากคุณมีผู้นำคนหนึ่งและคนใดคนหนึ่งต่อท้ายมันก็ง่ายมาก อย่างไรก็ตามหากคุณมีแถบนำทางหลายรายการไม่ว่าจะเป็นส่วนนำหน้าหรือส่วนท้ายคุณจำเป็นต้องล้อมด้วย 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

นอกจากนี้ในการตอบเปาโรหิตย์ 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.