38

几周前我刚刚开始使用 SwiftUI,我正在学习。今天我遇到了一个问题。

当我展示一个带有 navigationBarItems 按钮的工作表,然后关闭 ModalView 并返回到 ContentView 时,我发现自己无法再次单击 navigationBarItems 按钮。

我的代码如下:

struct ContentView: View {

    @State var showSheet = false

    var body: some View {
        NavigationView {
            VStack {
                Text("Test")
            }.sheet(isPresented: self.$showSheet) {
                ModalView()
            }.navigationBarItems(trailing:
                Button(action: {
                    self.showSheet = true
                }) {
                    Text("SecondView")
                }
            )
        }
    }
}

struct ModalView: View {

    @Environment(\.presentationMode) var presentation

    var body: some View {
        VStack {
            Button(action: {
                self.presentation.wrappedValue.dismiss()
            }) {
                Text("Dismiss")
            }
        }
    }
}
4

7 回答 7

61

我认为这是因为presentationMode不是从演示者视图继承的,所以演示者不知道模式已经关闭。您可以通过添加presentationMode到演示者(在本例中为 ContentView)来解决此问题。

struct ContentView: View {

    @Environment(\.presentationMode) var presentation
    @State var showSheet = false

    var body: some View {
        NavigationView {
            VStack {
                Text("Test")
            }.sheet(isPresented: self.$showSheet) {
                ModalView()
            }.navigationBarItems(trailing:
                Button(action: {
                    self.showSheet = true
                }) {
                    Text("SecondView")
                }
            )
        }
    }
}

在 Xcode 12.5 上测试。

这是完整的工作 示例

于 2020-04-19T20:34:27.107 回答
15

这似乎是 SwiftUI 中的一个错误。我仍然在 Xcode 11.5 / iOS 13.5.1 中看到这个问题。navigationBarMode 没有任何区别。

我向 Apple 提出了问题:


FB7641003 - 点击显示工作表的 navigationBarItem 按钮有时无法识别

您可以使用随附的示例项目SwiftUISheet(也可通过https://github.com/ralfebert/SwiftUISheet获得)来重现该问题。它只是显示导航栏按钮的工作表。运行应用程序并反复点击导航栏中的“加号”按钮。当工作表弹出时,向下滑动将其关闭。只会处理对按钮的一些点击,通常会忽略点击。

在 Xcode 11.4 (11E146) 和 iOS 13.4 (17E255) 上测试。

于 2020-03-26T19:29:31.063 回答
3

我仍然在 Xcode 13 RC 和 iOS 15 上看到这个问题。不幸的是,上面的解决方案对我不起作用。我最终做的是向工具栏添加一个小的文本视图,其内容根据.showingSheet属性的值而变化。

struct ContentView: View {
    @State private var showingSheet = false

    var body: some View {
        NavigationView {
            VStack {
                Text("Content view")
                Text("Swift UI")
            }
            .sheet(isPresented: $showingSheet) {
                Text("This is a sheet")
            }
            .navigationTitle("Example")
            .toolbar {
                ToolbarItemGroup(placement: .navigationBarTrailing) {
                    // Text view workaround for SwiftUI bug
                    // Keep toolbar items tappable after dismissing sheet
                    Text(showingSheet ? " " : "").hidden()
                    Button(action: {
                        self.showingSheet = true
                    }) {
                        Label("Show Sheet", systemImage: "plus.square")
                    }
                }
            }
        }
    }
}

我意识到这并不理想,但这是对我有用的第一件事。我的猜测是,根据属性更改Text.showingSheet视图的内容会强制 SwiftUI 完全刷新工具栏组。

于 2021-09-21T15:18:59.710 回答
2

非常hacky,但这对我有用:

Button(action: {
    self.showSheet = true
}) {
    Text("SecondView")
    .frame(height: 96, alignment: .trailing)
}
于 2020-06-05T06:15:54.617 回答
1

到目前为止,我仍然可以在关闭其呈现的表格后立即观察到导航按钮的混乱。

仅供参考,我正在使用 UINavigationController 包装器作为解决方法。它运作良好。

不幸的是,我确信这种错误越多,iOS 开发人员广泛使用 SwiftUI 的时间就越远。因为这些太基础了,不容忽视。

于 2020-05-14T02:48:29.963 回答
1

非常hacky,但这对我有用:

我有同样的问题。这个解决方案对我有用。

struct ContentView: View {

    @State var showSheet = false

    var body: some View {
        NavigationView {
            VStack {
                Text("Test")
            }.sheet(isPresented: self.$showSheet) {
                ModalView()
            }.navigationBarItems(trailing:
                Button(action: {
                    self.showSheet = true
                }) {
                    Text("SecondView")
                        // this is a workaround
                        .frame(height: 96, alignment: .trailing)
                }
            )
        }
    }
}
于 2020-09-26T13:23:00.680 回答
1

只有@adamwjohnson5 的回答对我有用。我不喜欢这样做,但它是唯一适用于 Xcode 13.1 和 iOS 15.0 的解决方案。这是我的代码,供有兴趣查看 iOS 15.0 目标代码的任何人使用:

var body: some View {
    NavigationView {
        mainContentView
            .navigationTitle(viewModel.navigationTitle)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    PlusButton {
                        viewModel.showAddDialog.toggle()
                    }
                    .frame(height: 96, alignment: .trailing) // Workaroud, credit: https://stackoverflow.com/a/62209223/5421557
                    .confirmationDialog("CatalogView.Add.DialogTitle", isPresented: $viewModel.showAddDialog, titleVisibility: .visible) {
                        Button("Program") {
                            viewModel.navigateToAddProgramView.toggle()
                        }
                        
                        Button("Exercise") {
                            viewModel.navigateToAddExerciseView.toggle()
                        }
                    }
                }
            }
            .sheet(isPresented: $viewModel.navigateToAddProgramView, onDismiss: nil) {
                Text("Add Program View")
            }
            .sheet(isPresented: $viewModel.navigateToAddExerciseView, onDismiss: nil) {
                AddEditExerciseView(viewModel: AddEditExerciseViewModel())
            }
    }
    .navigationViewStyle(.stack)
}
于 2021-12-30T19:23:27.513 回答