#swift #macos #swiftui #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
элемента : один с первой строкой 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)
}
}
}
}
Панель поиска-это текстовое поле на панели инструментов.
В 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)
}
}
Комментарии:
1. developer.apple.com/wwdc21/10018
2. Где на этом сайте? И еще, это не macOS 12, это Биг Сур, так
.searchable
что не работает.
Ответ №1:
Вот отредактированный ответ, чтобы люди не жаловались:
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
})
}
Комментарии:
1. @Кевин Сеймур, о чем ты говоришь. Если вы прочитали код в моем вопросе, то ответ ясен. Но поскольку я не хочу слышать жалоб, вот оно. полный ответ
2. Я согласен. Я думаю, что, возможно, я нажал не ту кнопку и удалил свой комментарий. Ваше здоровье.