繁体   English   中英

SwiftUI - 显示工作表后导航栏按钮不可点击

[英]SwiftUI - Navigation bar button not clickable after sheet has been presented

几周前我刚刚开始使用 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")
            }
        }
    }
}

我认为发生这种情况是因为presentationMode不是从演示者视图继承的,所以演示者不知道模式已经关闭。 您可以通过将presentationMode添加到presenter(在本例中为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 上测试。

这是完整的工作示例

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

我向 Apple 提出了问题:


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

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

使用 iOS 13.4 (17E255) 在 Xcode 11.4 (11E146) 上进行测试。

我仍然看到 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")
                    }
                }
            }
        }
    }
}

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

这是一个与.large navigationBarItem 相关的Bug 您现在可以将其设置为.inline到 go 周围:

    NavigationView {
        ,,,

        .navigationBarTitle(Text(""), displayMode: .inline)
    }

要查看错误:向下拖动按钮以使其在.large模式下工作;)

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

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

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

非常hacky,但这对我有用:

Button(action: {
    self.showSheet = true
}) {
    Text("SecondView")
    .frame(height: 96, alignment: .trailing)
}

非常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)
                }
            )
        }
    }
}

只有@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)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM