前语

在上一篇文章中,咱们介绍了 SwiftData 的增修正查的四种操作。这篇文章,咱们将介绍一下怎么对 SwiftData 进行数据排序以及数据过滤。

数据排序

假如想对查询的数据进行排序,最简单的办法便是运用 @Query 宏的额定选项。比如咱们想让 Item 目标的数据以 name 进行排序,原始代码:

@Model
final class Item {
    var timestamp: Date
    var name: String
    init(timestamp: Date, name: String) {
        self.timestamp = timestamp
        self.name = name
    }
}
@Query private var items: [Item]

下面是以 name 特点进行正序排序的代码:

@Query(sort: Item.name)
private var items: [Item]

当然,咱们也能够修正 order 参数的值,对数据以 name 特点进行逆向排序:

@Query(sort: Item.name, order: .reverse)

但是这种办法是有局限性的,那便是只能处理一个特点,假如你的需求是需求归纳多个特点进行排序,比如对 Item 进行 name 的升序然后按 timestamp 进行降序。那么你需求运用 SortDescriptor 数组。

@Query(sort: [SortDescriptor(Item.name), SortDescriptor(Item.timestamp, order: .reverse)])

需求注意的是,SortDescriptor 的运用是不会限制运用个数,所以你能够依据自己的需求添加任意个 SortDescriptor。 SwiftData 会依据添加顺序一个一个的去执行。

数据排序说完,接下来咱们看一下假如对 SwiftData 进行数据过滤。

数据过滤

SwiftData 是经过谓词来进行数据过滤的:即经过测验是否符合条件来决定是否添加到返回的数组中。详细到代码方面,便是运用 #Predicate 宏来完成的。它会承受咱们编写的 Swift 代码,将其转换为底层数据库能够辨认的过滤器。

下面来看一下 #Predicate 在代码中,详细是怎么运用的。假设,当 name长度小于五位,咱们就不显示该目标:

init(sort: SortDescriptor<Item>) {
    _items = Query(filter: #Predicate {
        $0.name.count > 5
    }, sort: [sort])
}

在上述代码中,咱们给 #Predicate 传入了一个闭包,闭包的内容便是每个 item 目标的 name 长度需求大于五位。

在实践的 SwiftUI 项目中,假如咱们需求完成依据用户的查找来进行数据的过滤,则需求结合 searchable() 修饰符运用。

首要,咱们需求声明一个特点用来承受用户输入的查找文本:

@State private var searchText = ""

接着,咱们需求供给一个输入框,让用户输入想查找的内容,这个运用 searchable() 修饰符完成:

.searchable(text: $searchText)

然后,便是详细完成数据过滤的代码了,同样也是运用 #Predicate 宏来完成:

init(sort: SortDescriptor<Item>, searchString: String) {
    _items = Query(filter: #Predicate {
        if searchString.isEmpty {
            return true
        } else {
            return $0.name.localizedStandardContains(searchString)
        }
    }, sort: [sort])
}

Tips:一般来说,.localizedStandardContains() 是最好的办法用来完成用户的文本查找。假如运用惯例的 contains(),它是区分大小写的。

由于你改变了初始化办法,所以 #Preview 中的代码你也需求修正,不然编译是不经过的。由于是预览页面,所以 searchString 咱们直接传递一个空字符串即可。

#Preview {
    ItemListView(sort: SortDescriptor(Item.name), searchString: "")
}

最后一步,由于咱们是修正的 ItemListView 的代码,所以在创建 ItemListView 的时候咱们也需求修正其初始化办法,然后将当时的 sortOrder 和查找文本传递进去:

ItemListView(sort: sortOrder, searchString: searchText)

这样,咱们就完成了在 SwiftUI 页面中运用 SwiftData 的数据过滤功能。