【问题标题】:Why does a SwiftUI TextField inside a navigation bar only accept input one character at a time为什么导航栏中的 SwiftUI TextField 一次只接受输入一个字符
【发布时间】:2020-04-20 14:54:09
【问题描述】:

我想让用户过滤长列表中的数据,以便更轻松地找到匹配的标题。

我在导航栏中放置了一个 TextView:

.navigationBarTitle(Text("Library"))
.navigationBarItems(trailing: TextField("search", text: $modelData.searchString)

我有一个响应搜索字符串变化的可观察对象:

class DataModel: ObservableObject {
   @Published var modelData: [PDFSummary]
   @Published var searchString = "" {
            didSet {
                if searchString == "" {
                    modelData =  Realm.studyHallRealm.objects(PDFSummary.self).sorted(by: { $0.name < $1.name })
                } else {
                    modelData =  Realm.studyHallRealm.objects(PDFSummary.self).sorted(by: { $0.name < $1.name }).filter({ $0.name.lowercased().contains(searchString.lowercased()) })
                }
            }
        }

一切正常,除了我必须在输入每个字母后点击该字段。出于某种原因,输入每个字母后焦点从字段中移开(除非我点击建议的自动更正 - 整个字符串一次正确添加到字符串中)

【问题讨论】:

    标签: swiftui textfield


    【解决方案1】:

    问题在于完全重建NavigationView,导致文本字段焦点下降。

    这是工作方法。使用 Xcode 11.4 / iOS 13.4 测试

    我们的想法是避免重建 NavigationView 基于 SwiftUI 引擎更新修改过的视图的知识,因此使用分解我们在本地进行修改并仅在子视图之间直接传输所需的值而不影响顶部 @987654325 @,因此最后保留的立场。

    class QueryModel: ObservableObject {
        @Published var query: String = ""
    }
    
    struct ContentView: View {
        // No QueryModel environment object here - 
        //                implicitly passed down. !!! MUST !!!
    
        var body: some View {
            NavigationView {
                ResultsView()
                    .navigationBarTitle(Text("Library"))
                    .navigationBarItems(trailing: SearchItem())
            }
        }
    }
    
    struct ResultsView: View {
        @EnvironmentObject var qm: QueryModel // << injected here from top
        var body: some View {
            VStack {
                Text("Search: \(qm.query)") // receive query string
            }
        }
    }
    
    struct SearchItem: View {
        @EnvironmentObject var qm: QueryModel // << injected here from top
        @State private var query = "" // updates only local view
    
        var body: some View {
            let text = Binding(get: { self.query }, set: {
                self.query = $0; self.qm.query = $0;       // transfer query string
            })
            return TextField("search", text: text)
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView().environmentObject(QueryModel())
        }
    }
    

    【讨论】:

    • 这正是我所需要的。当我键入并点击删除时,列表会增长和缩小。再次感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 2020-09-02
    • 2020-05-18
    • 2016-03-28
    相关资源
    最近更新 更多