SwiftUI在导航离开后未正确关闭键盘

eqoofvh9  于 2023-01-25  发布在  Swift
关注(0)|答案(1)|浏览(129)

如果上次离开时显示键盘,则在导航堆栈中向上一级时,我的SwiftUI出现问题。
1.在第一个屏幕中,将焦点放在文本字段上,然后显示键盘
1.触发导航链接以在导航堆栈中显示第二个视图
1.点击后退返回到第一个视图
预期:键盘应仍显示或关闭,屏幕上的所有控件应按编程响应
观察到:键盘未显示,但屏幕下半部分无响应,好像键盘仍在那里阻止点击输入
特别是在下面的示例代码中触发它:
1.聚焦搜索字段以显示键盘
1.点击任何链接,例如“第0行”
1.点击“返回”
观察到:“safeAreaInset bottom”视图移动到屏幕中间。其下方区域对点击无响应。
测试环境:Xcode 14.1,iOS 16.1,解决方案需要支持iOS 15.0

struct KeyboardDismissSampleView: View {
    
    @Environment(\.dismissSearch) private var dismissSearch
    
    @State var searchText: String = ""
    @State var showDetailView = false
    
    var body: some View {
        NavigationView {
            ScrollView {
                NavigationLink(isActive: $showDetailView) {
                    Text("showDetailView")
                } label: {
                    EmptyView()
                }

                VStack(alignment: .leading, spacing: 15) {
                    ForEach(0..<50) { i in
                        
                        // Version A
//                        NavigationLink {
//                            Text("Row \(i)")
//                        } label: {
//                            Text("Row \(i)")
//                                .frame(maxWidth: .infinity, alignment: .leading)
//                        }
                        
                        // Version B
                        Button("Row \(i)") {
//                            UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
                            dismissSearch()
                            showDetailView = true
                        }
                        .frame(maxWidth: .infinity, alignment: .leading)
                    }
                }
                .padding()
            }
            .safeAreaInset(edge: .bottom, content: {
                // This view is just to visually show the issue
                // Even without his safeAreaInset section, the area covered by the keyboard is still not responding to taps
                Text("safeAreaInset bottom")
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(Color.yellow)
            })
            .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
        }
    }
}

我试过使用resignFirstResponder和dismissSearch,它们要么有同样的问题,要么引入了其他问题。这个日志显示在Xcode控制台中,显然你不能同时关闭键盘和导航:
pushViewController:animated: called on <_TtGC7SwiftUI41StyleContextSplitViewNavigationControllerVS_19SidebarStyleContext_ 0x10f01c600> while an existing transition or presentation is occurring; the navigation stack will not be updated.
我已经研究了这些相关问题:
Keyboard dismiss not working properly when dismiss the view swiftui
Keyboard not dismissing in SwiftUI with onTapGesture
SwiftUI: dismiss List searchable keyboard?

von4xj4u

von4xj4u1#

看来

UIApplication.shared.windows.first?.endEditing(true)

解决了该问题,尽管它确实会生成弃用警告。
请注意,我删除了注解掉的代码,并用新的NavigationStack替换了NavigationView,但这并不是修复它的方法。

struct ContentView: View {
    
    @State var searchText: String = ""
    @State private var path = NavigationPath()
    
    var body: some View {
        NavigationStack(path: $path) {
            ScrollView {
                VStack(alignment: .leading, spacing: 15) {
                    ForEach(0..<50) { i in
                        Button("Row \(i)") {
                            UIApplication.shared.windows.first?.endEditing(true)
                            path.append(i)
                        }
                        .frame(maxWidth: .infinity, alignment: .leading)
                    }
                }
                .padding()
            }
            .navigationDestination(for: Int.self) { _ in
                Text("show detail view")
            }
            .safeAreaInset(edge: .bottom) {
                Text("safeAreaInset bottom")
                    .padding()
                    .frame(maxWidth: .infinity)
                    .background(Color.yellow)
                
            }
        }
        .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always))
    }
}

相关问题