拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 如何在macOS上使用SwiftUI搜索表格?

如何在macOS上使用SwiftUI搜索表格?

白鹭 - 2022-03-04 2143 0 0

在 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 上,searchableTable容器不支持修饰符

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方法和它的作品,但它可能是一个坏的限制,也可以是更高级的可以通过合并来实作。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *