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

a1o7rhls  于 2023-08-07  发布在  Swift
关注(0)|答案(8)|浏览(164)

我刚开始使用SwiftUI几周前,我还在学习。今天我遇到了一个问题。
当我展示一个带有navigationBarItems-button的工作表,然后关闭ModalView并返回ContentView时,我发现自己无法再次点击navigationBarItems-button。
代码如下:

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")
            }
        }
    }
}

字符串

qmelpv7a

qmelpv7a1#

我认为这是因为presentationMode不是从presenter视图继承的,所以presenter不知道模态已经关闭。您可以通过将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上测试。
下面是完整的工作example

hfyxw5xn

hfyxw5xn2#

这似乎是SwiftUI中的一个bug。在Xcode 11.5 / iOS 13.5.1中,我仍然看到这个问题。navigationBarMode没有什么不同。
我向苹果提出了一个问题:
FB 7641003-点击navigationBarItem按钮,显示有时无法识别的工作表
您可以使用附带的示例项目SwiftUISheet(也可以通过https://github.com/ralfebert/SwiftUISheet获得)来重现该问题。它只是从一个导航栏按钮中显示一个工作表。运行应用程序,并反复点击导航栏中的“加号”按钮。当工作表弹出时,通过向下滑动将其关闭。只有一些点击按钮将被处理,通常点击被忽略。
在Xcode 11.4(11 E146)和iOS 13.4(17 E255)上测试。

hkmswyz6

hkmswyz63#

这是一个非常简单的方法,但它对我很有效:

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

字符串

czfnxgou

czfnxgou4#

我在Xcode 13 RC和iOS 15中仍然看到这个问题。不幸的是,上面的解决方案对我不起作用。我最终做的是向工具栏添加一个小的Text视图,其内容根据.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完全刷新工具栏组。

tuwxkamq

tuwxkamq5#

到目前为止,我仍然可以观察到导航按钮的混乱后,解雇其提出的工作表的权利。
FYI,我**使用UINavigationController Package 器作为解决方法。**它工作得很好。
不幸的是,我确信这种bug越多,iOS开发人员广泛使用SwiftUI的时间就越远。因为这些都是最基本的,不容忽视。

rslzwgfq

rslzwgfq6#

这是一个非常简单的方法,但它对我很有效:
我也有同样的问题。这个办法对我很有效。

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

字符串

dohp0rv5

dohp0rv57#

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

字符串

r7knjye2

r7knjye28#

核心问题是导航栏项目框架未对齐。安全的解决方案是在每次模式关闭时强制重新创建栏项。是的,重新创建视图效率很低,但是由于栏按钮非常简单,这样的开销似乎并不明显。
所以,继续快闪族寻找自己的解决办法,这是我的:
1.在视图中,放置:

@Environment(\.presentationMode) var presentationMode

字符串
这将迫使视图在每次呈现或从视图中删除一个模态时进行更新;
1.使用随机ID声明工具栏项

ToolbarItem(id: UUID().uuidString, placement: .navigationBarLeading) { ... }


这样,每次更新视图时,它们都会被重新创建(因为每次都会随机生成新的ID)

相关问题