我想允许用户过滤长列表中的数据,以便更轻松地找到匹配的标题。
我已经将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()) })
}
}
}
一切正常,除了输入每个字母后我必须点击字段。由于某些原因,输入每个字母后,焦点将从字段中移开(除非我点击建议的自动更正-整个字符串立即正确添加到字符串中)
问题是NavigationView
完全重建,导致文本字段焦点丢失。
这是工作方法。经过Xcode 11.4 / iOS 13.4测试
这样做的目的是避免NavigationView
基于SwiftUI引擎仅更新修改后的视图的知识而进行重建,因此使用分解功能,我们可以进行本地修改,并且仅在不影响top的子视图之间传输所需的值NavigationView
,从而保持最后一个立场。
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())
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句