在 iOS 和 iPadOS 15 上的 SwiftUI 中,我們可以添加一個搜索欄來使用searchable修飾符過濾串列:
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@State private var searchTerm = ""
@State private var selection = Set<Video.ID>()
private var fetchRequest: FetchRequest<Video>
private var searchResults: [Video] {
if searchTerm.isEmpty {
return fetchRequest.wrappedValue.filter { _ in true }
} else {
return fetchRequest.wrappedValue.filter { $0.matching(searchTerm) }
}
}
var body: some View {
NavigationView {
List {
ForEach(searchResults) { item in
VideoListCellView(video: item)
}
}.searchable(text: $searchTerm, prompt: "Video name") // <-- HERE
}
}
}
但是,在 macOS 上,searchable新Table容器不支持該修飾符:
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(sortDescriptors: [SortDescriptor(\.addDate, order: .reverse)], animation: .default)
private var videos: FetchedResults<Video>
@State
private var selection = Set<Video.ID>()
var body: some View {
NavigationView {
Table(videos, selection: $selection, sortOrder: $videos.sortDescriptors) {
TableColumn("Title") {
Text($0.title)
}
TableColumn("Added") {
Text($0.addDate)
}.width(120)
TableColumn("Published") {
Text($0.publishedAt)
}.width(120)
TableColumn("Duration") {
Text($0.duration)
}.width(50)
}.searchable(text: $searchTerm, prompt: "Video name") // <-- GENERATES ERROR
}
}
}
嘗試使用它會在以下位置生成編譯錯誤var body: some View:
The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
是否有另一種Table在 macOS上搜索 a 的方法,或者此功能尚不支持?
uj5u.com熱心網友回復:
正如斯科特建議的那樣,解決方案是將.searchable修飾符添加到NavigationView而不是Table:
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(sortDescriptors: [SortDescriptor(\.addDate, order: .reverse)], animation: .default)
private var videos: FetchedResults<Video>
@State private var selection = Set<Video.ID>()
@State private var searchTerm = ""
private var searchResults: [Video] {
if searchTerm.isEmpty {
return videos.filter { _ in true }
} else {
return videos.filter { $0.matching(searchTerm) }
}
}
var body: some View {
NavigationView {
Table(searchResults, selection: $selection, sortOrder: $videos.sortDescriptors) {
TableColumn("Title", value: \.title) {
Text($0.title)
}
TableColumn("Added", value: \.addDate) {
Text($0.addDate)
}.width(120)
TableColumn("Published", value: \.publishedAt) {
Text($0.publishedAt)
}.width(120)
TableColumn("Duration") {
Text($0.duration)
}.width(50)
}
}.searchable(text: $searchTerm, prompt: "Video name") // <-- HERE
}
}
uj5u.com熱心網友回復:
您可以通過使用特定的 Binding 變數更新獲取請求的謂詞來解決此問題。
以下解決方案基于 2021 年 WWDC 視頻將核心資料并發性引入 Swift 和 SwiftUI中的一個示例,該示例在串列中使用,這也是我使用它的目的,但我在我的一張表上對其進行了測驗,并且效果同樣好.
@State private var searchText: String = ""
var query: Binding<String> {
Binding {
searchText
} set: { newValue in
searchText = newValue
if newValue.isEmpty {
videos.nsPredicate = NSPredicate(value: true)
} else {
videos.nsPredicate = NSPredicate(format: "name BEGINSWITH[c] %@", newValue)
}
}
}
然后你用這個變數傳遞給 .searchable
Table(videos, selection: $selection, sortOrder: $videos.sortDescriptors) {
// ...
}
.searchable(text: query, prompt: "Search instrument")
這個解決方案的缺點是每個輸入的字母都會執行一個新的提取請求。我想速戰速決通過增加if newValue.count < 3 { return }在else該的query set方法和它的作品,但它可能是一個壞的限制,也可以是更高級的可以通過合并來實作。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/408694.html
標籤:
