我一直在try 构建的SwiftUI应用程序的排序和分组过程.

我看到的所有教程在排序和过滤方面都相当"基础",特别是在使用SwiftData时.

我想要整合的不仅是按其中一个属性和正向/反向排序,而且还将数据分组.

例如,这是Apple的Earthquake项目的代码(为了简洁起见,删除了一些项目):

struct QuakeList: View {
    @Environment(ViewModel.self) private var viewModel
    @Environment(\.modelContext) private var modelContext
    @Query private var quakes: [Quake]

    init(
        sortParameter: SortParameter = .time,
        sortOrder: SortOrder = .reverse
    ) {
        switch sortParameter {
            case .time:
                _quakes = Query(sort: \.time, order: sortOrder)
            case .magnitude:
                _quakes = Query(sort: \.magnitude, order: sortOrder)
        }
    }

他们在这里所做的是将sortParametersortOrder传递给这个视图,并在更改/更新时重新呈现视图.

我如何扩展它,使它也可以处理分组,使quakes变量实际上是一个多维数组,甚至是一个字典.

例如,我试图这样做来执行渲染:

enum GroupOption { // New grouping for Section
    case time
    case magnitude
    case none
}

struct ListScreen: View {
    @Environment(ViewModel.self) private var viewModel
    @Environment(\.modelContext) private var modelContext
    @Query private var quakes: [Quake]
    @State private var groupedQuakes: [[Quake]] = [] // New multidimensional array

    init(
        sortParameter: SortParameter = .time,
        sortOrder: ComparisonResult = .orderedAscending, // using ComparisonResult to store the enum value in defaults
        sortGrouping: GroupOption = .none
    ) {
        switch (sortParameter, sortOrder) {
            case (.time, .orderedAscending):
                _quakes = Query(sort: \.time, order: .forward)
            case (.time, .orderedDescending):
                _quakes = Query(sort: \.time, order: .reverse)

            case (.magnitude, .orderedAscending):
                _quakes = Query(sort: \.magnitude, order: .forward)
            case (.magnitude, .orderedDescending):
                _quakes = Query(sort: \.magnitude, order: .reverse)

            default:
                _quakes = Query(sort: \.time, order: .forward)
        }

        switch sortGrouping {
            case .time:
                groupedQuakes = Dictionary(grouping: _quakes.wrappedValue, by: { $0.time })
                    .sorted(by: { $0.key < $1.key })
                    .map({ $0.value })
            case .magnitude:
                groupedQuakes = Dictionary(grouping: _quakes.wrappedValue, by: { $0.magnitude })
                    .sorted(by: { $0.key < $1.key })
                    .map({ $0.value })
            case .none:
                groupedQuakes = [_quakes.wrappedValue]
        }
    }

但是,当我在视图主体中使用它时,它是空的.因此,从// 1切换到// 2会使数据数组返回空.

// 1
List(quakes) { quake in
  QuakeRow(quake: quake)
}

// 2
List {
  ForEach(groupedQuakes, id: \.self) { group in
    Section {
      ForEach(group) { quake in
        QuakeRow(quake: quake)
      }
    } header: {
      groupHeader(for: group)
    }
  }
}
// ...
func groupHeader(for group: [Quake]) -> Text {
  guard let group = group.first else { return Text("Unknown") }
  switch groupOption {
    case .time:
      return Text(group.time.formatted(date: .numeric, time: .omitted))
    case .magnitude:
      return Text("\(group.magnitude)")
    case .none:
      return Text("All quakes")
  }
}

因此,当我返回一般@Query private var quakes: [Quake]时,有一个数组返回数据.

使用Apple测试项目中包含的排序,quakes个被正确排序.

一旦我try 添加分组和排序,数据返回空array.

我是不是忽略了什么?

推荐答案

好吧,经过更多的研究,目前的状态是目前没有SwiftData解决方案.

然而,有两种方法可以实现这个计算变量(Joakim Danielson建议的)和Swift包.

计算变量

ListScreen的示例代码中,我们将switch sortGrouping { ... }移动到计算(computed)属性中,并为当前属性添加@Binding以将多维数组赋给:

struct ListScreen: View {
    @Environment(ViewModel.self) private var viewModel
    @Environment(\.modelContext) private var modelContext
    @Query private var quakes: [Quake]

    @Binding var sortGrouping: GroupOption // <-- new binding
    private var groupedQuakes: [[Quake]] { // <-- new computed property
        switch sortGrouping {
            case .time:
                groupedQuakes = Dictionary(grouping: _quakes.wrappedValue, by: { $0.time })
                    .sorted(by: { $0.key < $1.key })
                    .map({ $0.value })
            case .magnitude:
                groupedQuakes = Dictionary(grouping: _quakes.wrappedValue, by: { $0.magnitude })
                    .sorted(by: { $0.key < $1.key })
                    .map({ $0.value })
            case .none:
                groupedQuakes = [_quakes.wrappedValue]
        }
    }

    init(
        sortParameter: SortParameter = .time,
        sortOrder: ComparisonResult = .orderedAscending, // using ComparisonResult to store the enum value in defaults
        sortGrouping: Binding<GroupOption>
    ) {
        _sortGrouping = sortGrouping // <-- assign the Binding

        switch (sortParameter, sortOrder) {
            case (.time, .orderedAscending):
                _quakes = Query(sort: \.time, order: .forward)
            case (.time, .orderedDescending):
                _quakes = Query(sort: \.time, order: .reverse)

            case (.magnitude, .orderedAscending):
                _quakes = Query(sort: \.magnitude, order: .forward)
            case (.magnitude, .orderedDescending):
                _quakes = Query(sort: \.magnitude, order: .reverse)

            default:
                _quakes = Query(sort: \.time, order: .forward)
        }
    }

然后,当@Binding中的sortGrouping更改时,视图将重新呈现,分组您的数据.

我不确定它会如何处理过于复杂的单元,但它适用于大约200个单元,图像,标题和子标题,没有任何真正明显的延迟.


Swift套装—SectionedQuery

相当解释性的README文件,但我唯一看不到的是有不同的组类型.根据我刚刚测试的结果,您只能设置一种类型并将其用作组,这意味着您的组是相当固定的.

Ios相关问答推荐

在Android和iOS上从后台恢复应用程序后,inappwebview上出现白屏?

当包含UITextView的inputAccessoryView显示键盘时,iOS UITableView内容会出现UINavigationBar奇怪的错误

如何在SwiftUI中以一定Angular 绘制直线(&A)

SwiftUI中的Tap手势无法识别视图上的偏移变化

在 iOS 上启用明文本地流量在 .NET MAUI 中不起作用

垂直分页 UIScrollView 高度不正确

iOS 如何使用 Alamofire 解析 JSON 可编码数组

SwiftUI 切换语句

我可以使用同一个 Firebase 应用将多个 Flutter 应用添加到一个 Firebase 数据库吗?

使用 RxDatasources 作为数据源时如何填充自定义页眉/页脚视图

SwiftUI NavigationLink 立即加载目标视图,无需单击

iOS swift从另一个数组中删除一个数组的元素

如何在 Xcode 4 中切换 .h 和 .m

界面生成器中 UIView 的边框 colored颜色 不起作用?

iOS 10 / Xcode 8 设备上的 NSLog 似乎被截断了?为什么?

用 PC 调试 ipad safari

如何在上传到服务器之前在 iOS 上压缩/调整图像大小?

如何在 UILabel 中找到文本子字符串的 CGRect?

如何关闭 iOS 键盘?

快速从 NSTimeInterval 转换为小时、分钟、秒、毫秒