Swiftui:使用自定义搜索栏过滤列表
我已经创建了一个使用textfield
的自定义搜索栏,并尝试使用它过滤我的列表。
[![Enter映像说明在此处] [1]] [1]
我的列表由a到z部分组成。现在,我在搜索返回nil时要过滤部分和列表有问题。这是我的代码:
@State private var searchText = ""
let lists = loadGlossary().keys.sorted()
let glossary = loadGlossary()
var body: some View {
VStack(spacing: -10) {
//Navigation bar
NavigationBarView(title: "Glossary", action: {}, titleColor: .primary, closeColor: .primary.opacity(0.5))
.padding()
//Search Bar
TextField("Search", text: $searchText)
.padding()
.frame(height: 45)
.background(.gray.opacity(0.1))
.clipShape(RoundedRectangle(cornerRadius: 10))
.padding()
.overlay {
HStack {
Spacer()
Button {
searchText = ""
} label: {
Label("clear", systemImage: "xmark.circle.fill")
.foregroundColor(.gray)
.opacity(searchText.isEmpty ? 0 : 1)
.padding(30)
}
.labelStyle(.iconOnly)
}
}
//List
List {
ForEach(Array(wordDict.keys).sorted(by: <), id: \.self) { character in
///Section
Section(header: Text("\(character)").font(Font.system(size:18, weight: .bold, design: .serif)).foregroundColor(.primary)) {
///List
ForEach(wordDict[character] ?? [""], id: \.self) { word in
VStack(alignment: .leading, spacing: 5) {
Text(word)
.font(.system(size: 17, weight: .bold, design: .serif))
Divider()
Text(getDescription(word))
.foregroundColor(.secondary)
}
}
.padding()
}
}
.listRowSeparator(.hidden)
}
.listStyle(.plain)
.padding(.top)
}
}
如果您帮助正确过滤部分和项目,我将很感激。
编辑: 更改:
@State private var wordDict: [String:[String]] = [:]
func loadData() -> [String:[String]] {
let letters = Set(lists.compactMap( { $0.first } ))
var dict: [String:[String]] = [:]
for letter in letters {
dict[String(letter)] = lists.filter( { $0.first == letter } ).sorted()
}
return dict
}
并在此处加载第一个数据:
.onAppear {
wordDict = loadData()
}
我添加
TextField("Search", text: $searchText)
.onChange(of: searchText) {
wordDict = getFilteredWords(query: $0)
}
对于textfield
,
I have created a custom search bar with TextField
and trying to filter my List with it.
[![enter image description here][1]][1]
My list consists of A to Z sections. Now I have a problem with filtering both section and list while searching which is returning nil. Here is my code:
@State private var searchText = ""
let lists = loadGlossary().keys.sorted()
let glossary = loadGlossary()
var body: some View {
VStack(spacing: -10) {
//Navigation bar
NavigationBarView(title: "Glossary", action: {}, titleColor: .primary, closeColor: .primary.opacity(0.5))
.padding()
//Search Bar
TextField("Search", text: $searchText)
.padding()
.frame(height: 45)
.background(.gray.opacity(0.1))
.clipShape(RoundedRectangle(cornerRadius: 10))
.padding()
.overlay {
HStack {
Spacer()
Button {
searchText = ""
} label: {
Label("clear", systemImage: "xmark.circle.fill")
.foregroundColor(.gray)
.opacity(searchText.isEmpty ? 0 : 1)
.padding(30)
}
.labelStyle(.iconOnly)
}
}
//List
List {
ForEach(Array(wordDict.keys).sorted(by: <), id: \.self) { character in
///Section
Section(header: Text("\(character)").font(Font.system(size:18, weight: .bold, design: .serif)).foregroundColor(.primary)) {
///List
ForEach(wordDict[character] ?? [""], id: \.self) { word in
VStack(alignment: .leading, spacing: 5) {
Text(word)
.font(.system(size: 17, weight: .bold, design: .serif))
Divider()
Text(getDescription(word))
.foregroundColor(.secondary)
}
}
.padding()
}
}
.listRowSeparator(.hidden)
}
.listStyle(.plain)
.padding(.top)
}
}
I would be grateful if you help to properly filter sections and items.
EDITED:
Changes:
@State private var wordDict: [String:[String]] = [:]
func loadData() -> [String:[String]] {
let letters = Set(lists.compactMap( { $0.first } ))
var dict: [String:[String]] = [:]
for letter in letters {
dict[String(letter)] = lists.filter( { $0.first == letter } ).sorted()
}
return dict
}
and load the first data here:
.onAppear {
wordDict = loadData()
}
and for TextField
I have added:
TextField("Search", text: $searchText)
.onChange(of: searchText) {
wordDict = getFilteredWords(query: $0)
}
But when I clear the textfield of backspace the List won't update anymore
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
一种方法是您可以这样进行过滤:
这是您在以下假设下的特定需求的功能:
[string:[string]] 。 (例如“ a”:[“ Apple”,“ atari”])
searchText
的部分的部分。如果您想具有更高级的查询功能,该方法将相同,您只需要对下面的功能进行较小的调整。该函数有什么作用?
该函数采用
searchText
,并将您的WordDict
的所有条目与它进行比较。如果WordDict
条目包括searchText
的一部分,则保留。否则将其丢弃,因此后来未呈现。比较是病例不敏感的。之后,所有没有任何条目的类别也被丢弃,这些类别也可以防止您的搜索显示所有类别,即使它们不包含任何条目。如何使用它?
WordDict
在您的List> List
视图中使用getFilteredWords(QUERY:searchText)
。One approach would be that you could do the filtering like this:
Here is the function for your specific need under the following assumptions:
[String: [String]]
. (e.g. "A": ["apple", "Atari"])searchText
. If you want to have more advanced querying capabilities the method would be the same, you just have to make minor adjustments to the function below.What does the function do?
The function takes the
searchText
and compares all of the entries of yourwordDict
with it. If thewordDict
entry includes the part ofsearchText
somewhere, it is kept. Otherwise it is discarded and therefore later not rendered. The comparison is case insensitive. After that, all of the categories without any entries are also discarded which prevents that your search still shows all categories even if they don't contain any entries.How to use it?
wordDict
instances in yourList
View withgetFilteredWords(query: searchText)
.这是一种可能
或使用视图模型和发布者进行访问(示例)
Here is a possible way
or with view model and publishers to debounce (example)