首页 > 解决方案 > 用于过滤列表内容的搜索栏 (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
}

应用程序迭代数据模型上的每个元素并填充一个列表,其中 aNavigationLink有两个Text:一个带有 a 的第一行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 : $0.name.contains(searchText) })) { item in
    Text(item.name)
}

但是鉴于搜索栏是工具栏中的一个项目,并且我需要从数据模型中的所有文本中搜索过滤/重新填充列表,而不仅仅是列表,我什至该如何开始呢?如何过滤它?我需要填充一个新数组吗?如何访问搜索栏上的文本?它$searchText在我发布的代码中吗?我表演data.filter吗?

我已经没有尝试的想法了。

谢谢你。

编辑:

我有这种工作,但请注意。它弄乱了NavigationLink显示的方式,它在文本之前添加了随机空格。

代码:

var body: some View {
        NavigationView {
            List {
                ForEach(data.notes.filter { $0.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)
            }
        }

标签: swiftmacosswiftuimacos-big-sur

解决方案


这是编辑的答案,因此人们不会抱怨:

var body: some View {
        NavigationView {
                List(data.notes.filter { searchText.isEmpty ? true : $0.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
            })            

        }

推荐阅读