如何动态更改查询的排序顺序或谓词

温馨提示:本文最后更新于2025-01-20 14:12:40,某些文章具有时效性,若有错误或已失效,请在下方留言

要实现动态排序,您需要将@Query属性移至 SwiftUI 层次结构中的视图中 – 您需要将其放入子视图中,在其中可以使用依赖项注入提供排序值。

这意味着创建一个新的 SwiftUI,它使用@Query来显示您正在使用的 SwiftData 对象,然后将其嵌入到父视图中,该父视图为用户提供一些 UI 以选择排序顺序或过滤器。

例如,如果我们使用User模型,那么我们可能会创建一个如下所示的UserListingView

import SwiftData
import SwiftUI

struct UserListingView: View {
    @Query var users: [User]
    @Environment(\.modelContext) var modelContext

    var body: some View {
        List {
            ForEach(users) { user in
                NavigationLink(value: user) {
                    Text("\(user.name) is \(user.age) years old")
                }
            }
            .onDelete(perform: deleteUser)
        }
    }

    func deleteUser(_ indexSet: IndexSet) {
        for item in indexSet {
            let object = users[item]
            modelContext.delete(object)
        }
    }
}

然后回到ContentView中,我们可以在列表中创建它,如下所示:

NavigationStack {
    UserListingView()
}

此更改实际上并不处理排序 – 这只是使排序成为可能所需的设置。但是,因为我们现在有一个子视图,所以我们可以将值发送到那里来控制@Query属性包装器。

这总共需要四个步骤:

  1. 告诉UserListingView它需要以某种排序顺序创建。
  2. 当程序运行时,创建一些存储来保存当前活动的排序顺序。
  3. 创建UserListingView时将该值传递给它。
  4. 创建一些 UI 来根据用户的设置调整排序顺序。

第1步

需要调整UserListingView中的初始化程序,以便它使用从父视图传入的排序描述符来更改查询。这需要更改查询对象本身而不是其中的数组,因此我们需要像这样访问带下划线的属性名称:

init(sort: SortDescriptor<User>) {
    _users = Query(sort: [sort])
}

第2步

然后在ContentView中,我们添加一个属性来存储当前的排序顺序,并使用合理的默认值:

@State private var sortOrder = SortDescriptor(\User.name)

第3步

然后,我们可以将其传递到嵌入的UserListingView中,如下所示:

UserListingView(sort: sortOrder)

第4步

最后,我们需要ContentView中的一些 UI 来向用户提供各种排序选项,然后根据需要调整排序顺序。例如,我们可以将其放入工具栏中:

Menu("Sort") {
    Picker("Sort", selection: $sortOrder) {
        Text("Name")
            .tag(SortDescriptor(\User.name))

        Text("Age")
            .tag(SortDescriptor(\User.age, order: .reverse))

        Text("City")
            .tag(SortDescriptor(\User.city))
    }
    .pickerStyle(.inline)
}

这里发生的情况是,我们将排序选择从UserListingView上移了一级,这意味着我们现在可以动态控制它。每当排序顺序发生变化时,SwiftUI 都会自动重新创建UserListingView ,这反过来又会重新创建查询。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容