用于过滤列表内容的搜索栏 (macOS Big Sur)
Searchbar to filter contents on a list (macOS Big Sur)
我正在尝试通过搜索栏对数据模型实施搜索。
我的数据模型是以下结构:
struct NoteItem: Codable, Hashable, Identifiable {
let id: UUID
var text: String
var date = Date()
var dateText: String {
let df = DateFormatter()
df.dateFormat = "EEEE, MMM d yyyy, h:mm a"
return df.string(from: date)
}
var tags: [String] = []
var filename: String = ""
var changed: Bool = false
}
应用程序迭代数据模型上的每个元素并填充一个列表,其中 NavigationLink
有两个 Text
:一个是 TextEditor
的第一行,以及另一个用 datamodel.dateText
。列表中的每个项目都指向另一个视图,其中 TextEditor
显示完整的 datamodel.text
我要添加的搜索只能在 datamodel.text
上进行。代码如下:
struct AllNotes: View {
@EnvironmentObject private var data: DataModel
...
var body: some View {
NavigationView {
List(data.notes) { note in
NavigationLink(
destination: NoteView(note: note, text: note.text),
tag: note.id,
selection: $selectedNoteId
) {
VStack(alignment: .leading) {
Text(getTitle(noteText: note.text)).font(.body).fontWeight(.bold)
Text(note.dateText).font(.body).fontWeight(.light)
}
.padding(.vertical, 10)
}
}
.listStyle(InsetListStyle())
.frame(minWidth: 250, maxWidth: .infinity)
}
.toolbar {
ToolbarItem(placement: .automatic) {
TextField("Search...", text: $searchText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(minWidth: 200)
}
}
}
}
搜索栏是工具栏中的一个 TextField。
在iOS,过去,我做过类似的事情:
List(ListItems.filter({ searchText.isEmpty ? true : [=12=].name.contains(searchText) })) { item in
Text(item.name)
}
但考虑到搜索栏是工具栏中的一个项目,并且我需要使用数据模型中所有文本的搜索来过滤/重新填充列表,而不仅仅是列表,我将如何开始那个?如何过滤呢?我需要填充一个新数组吗?如何访问搜索栏上的文本?我发布的代码中是 $searchText
吗?我执行 data.filter
吗?
我 运行 没有想法可以尝试。
谢谢。
编辑:
我有这种工作,但请注意。它弄乱了 NavigationLink
的显示方式,它在文本前添加了 运行dom 空格。
代码:
var body: some View {
NavigationView {
List {
ForEach(data.notes.filter { [=13=].text.contains(searchText) || searchText.isEmpty }) { note in
NavigationLink(
destination: NoteView(note: note, text: note.text),
tag: note.id,
selection: $selectedNoteId
) {
VStack(alignment: .leading) {
Text(getTitle(noteText: note.text)).font(.body).fontWeight(.bold)
Text(note.dateText).font(.body).fontWeight(.light)
}
.padding(.vertical, 10)
}
}
.listStyle(InsetListStyle())
.frame(minWidth: 250, maxWidth: .infinity)
.alert(isPresented: $showAlert, content: {
alert
})
Text("Create a new note...")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
以下是经过编辑的答案,以免人们抱怨:
var body: some View {
NavigationView {
List(data.notes.filter { searchText.isEmpty ? true : [=10=].text.localizedCaseInsensitiveContains(searchText) }) { note in
NavigationLink(
destination: NoteView(note: note, text: note.text),
tag: note.id,
selection: $selectedNoteId
) {
VStack(alignment: .leading) {
Text(getTitle(noteText: note.text)).font(.body).fontWeight(.bold)
Text(note.dateText).font(.body).fontWeight(.light)
}
.padding(.vertical, 10)
}
}
.listStyle(InsetListStyle())
.frame(minWidth: 250, maxWidth: .infinity)
.alert(isPresented: $showAlert, content: {
alert
})
}
我正在尝试通过搜索栏对数据模型实施搜索。
我的数据模型是以下结构:
struct NoteItem: Codable, Hashable, Identifiable {
let id: UUID
var text: String
var date = Date()
var dateText: String {
let df = DateFormatter()
df.dateFormat = "EEEE, MMM d yyyy, h:mm a"
return df.string(from: date)
}
var tags: [String] = []
var filename: String = ""
var changed: Bool = false
}
应用程序迭代数据模型上的每个元素并填充一个列表,其中 NavigationLink
有两个 Text
:一个是 TextEditor
的第一行,以及另一个用 datamodel.dateText
。列表中的每个项目都指向另一个视图,其中 TextEditor
显示完整的 datamodel.text
我要添加的搜索只能在 datamodel.text
上进行。代码如下:
struct AllNotes: View {
@EnvironmentObject private var data: DataModel
...
var body: some View {
NavigationView {
List(data.notes) { note in
NavigationLink(
destination: NoteView(note: note, text: note.text),
tag: note.id,
selection: $selectedNoteId
) {
VStack(alignment: .leading) {
Text(getTitle(noteText: note.text)).font(.body).fontWeight(.bold)
Text(note.dateText).font(.body).fontWeight(.light)
}
.padding(.vertical, 10)
}
}
.listStyle(InsetListStyle())
.frame(minWidth: 250, maxWidth: .infinity)
}
.toolbar {
ToolbarItem(placement: .automatic) {
TextField("Search...", text: $searchText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(minWidth: 200)
}
}
}
}
搜索栏是工具栏中的一个 TextField。
在iOS,过去,我做过类似的事情:
List(ListItems.filter({ searchText.isEmpty ? true : [=12=].name.contains(searchText) })) { item in
Text(item.name)
}
但考虑到搜索栏是工具栏中的一个项目,并且我需要使用数据模型中所有文本的搜索来过滤/重新填充列表,而不仅仅是列表,我将如何开始那个?如何过滤呢?我需要填充一个新数组吗?如何访问搜索栏上的文本?我发布的代码中是 $searchText
吗?我执行 data.filter
吗?
我 运行 没有想法可以尝试。
谢谢。
编辑:
我有这种工作,但请注意。它弄乱了 NavigationLink
的显示方式,它在文本前添加了 运行dom 空格。
代码:
var body: some View {
NavigationView {
List {
ForEach(data.notes.filter { [=13=].text.contains(searchText) || searchText.isEmpty }) { note in
NavigationLink(
destination: NoteView(note: note, text: note.text),
tag: note.id,
selection: $selectedNoteId
) {
VStack(alignment: .leading) {
Text(getTitle(noteText: note.text)).font(.body).fontWeight(.bold)
Text(note.dateText).font(.body).fontWeight(.light)
}
.padding(.vertical, 10)
}
}
.listStyle(InsetListStyle())
.frame(minWidth: 250, maxWidth: .infinity)
.alert(isPresented: $showAlert, content: {
alert
})
Text("Create a new note...")
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
以下是经过编辑的答案,以免人们抱怨:
var body: some View {
NavigationView {
List(data.notes.filter { searchText.isEmpty ? true : [=10=].text.localizedCaseInsensitiveContains(searchText) }) { note in
NavigationLink(
destination: NoteView(note: note, text: note.text),
tag: note.id,
selection: $selectedNoteId
) {
VStack(alignment: .leading) {
Text(getTitle(noteText: note.text)).font(.body).fontWeight(.bold)
Text(note.dateText).font(.body).fontWeight(.light)
}
.padding(.vertical, 10)
}
}
.listStyle(InsetListStyle())
.frame(minWidth: 250, maxWidth: .infinity)
.alert(isPresented: $showAlert, content: {
alert
})
}