Nhiều trang tính (được xuất hiện :) không hoạt động trong SwiftUI


21

Tôi có ContentView này với hai chế độ xem phương thức khác nhau, vì vậy tôi đang sử dụng sheet(isPresented:)cho cả hai, nhưng dường như chỉ có cái cuối cùng được trình bày. Làm thế nào tôi có thể giải quyết vấn đề này? Hoặc không thể sử dụng nhiều trang tính trên một chế độ xem trong 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!")
            }
        }
    }
}

Đoạn mã trên biên dịch mà không có cảnh báo (Xcode 11.2.1).


Bạn chỉ có thể có một tờ. Giải pháp này cho thấy làm thế nào để có các cảnh báo khác nhau tương tự như tình huống của bạn và có thể dễ dàng được gửi lại stackoverflow.com/questions/58737767/
Andrew

Câu trả lời:


25

Vui lòng thử mã dưới đây

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
Giải pháp này có ý nghĩa và có thể mở rộng quy mô, cảm ơn!
turingtested

Đã thử mã này bằng câu lệnh chuyển đổi thay vì nếu ... khác và gặp lỗi "Không thể sử dụng câu lệnh đóng kiểm soát luồng đóng với trình xây dựng hàm 'ViewBuilder' vì nó không phải là ... nếu không phải là luồng điều khiển?
Aaron Surrain

Cảm ơn! Giải pháp này hoạt động
Adelmaer

Trang tính của bạn có cùng loại: Văn bản, còn loại khác thì sao? Theo như tôi thấy, nó không hoạt động.
Quang Hà

@ QuangHà cho rằng bạn cần phải làm theo cách khác. hoặc bạn có thể sử dụng hai hoặc nhiều SheetView như cách tiếp cận khác nhau mà bạn có
Rohit Makwana

11

Trường hợp của bạn có thể được giải quyết bằng cách sau (được thử nghiệm với 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)
    }
}

Tôi có một Thông báo nhưng nhiều Bool là sai nhưng một khi đúng (bên ngoài cơ thể) thì tôi muốn Thông báo của mình biết Bool nào là đúng và hiển thị một Thông báo nhất định
Dewan

6

Cũng có thể thêm trang tính vào một EmptyView được đặt trong nền của chế độ xem. Điều này có thể được thực hiện nhiều lần:

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

3

Bạn có thể thực hiện việc này đơn giản bằng cách nhóm các nút và các cuộc gọi .sheet lại với nhau. Nếu bạn có một hàng đầu và một dấu vết thì thật đơn giản. Tuy nhiên, nếu bạn có nhiều thanh điều hướng trong đầu hoặc cuối, bạn cần bọc chúng trong HStack và cũng bọc từng nút bằng lệnh gọi bảng tính trong VStack.

Đây là một ví dụ về hai nút đuôi:

            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

Ngoài câu trả lời của Rohit Makwana , tôi đã tìm ra cách trích xuất nội dung trang tính thành một hàm vì trình biên dịch đang gặp khó khăn trong việc kiểm tra loại khổng lồ của tôi View.

extension YourView {
    enum Sheet {
        case a, b
    }

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

Bạn có thể sử dụng nó theo cách này:

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

Nó làm cho mã sạch hơn và cũng làm giảm căng thẳng của trình biên dịch của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.