SectionedFetchRequest 是 SwiftUI 中用来将 Core Data 的数据按某个属性分组展示的机制,常用于 List 的分组展示,比如想按“日期”、“类别”、“国家”等属性把数据分区。
基本语法
@SectionedFetchRequest(
sectionIdentifier: \Entity.sectionAttribute,
sortDescriptors: [SortDescriptor(\Entity.sectionAttribute), SortDescriptor(\Entity.name)]
) private var items: SectionedFetchResults<String, Entity>
sectionIdentifier: 用哪个属性来分组。
sortDescriptors: 排序规则,通常要包括分组字段和列表内排序字段。
SectionedFetchResults<SectionIdentifier, Entity>: Section 的类型(比如 String, Date),和实体类型。
代码示例
按日期分组的外币购买记录
假设有一个实体叫 CurrencyRecord,属性如下:
1、currency: String
2、amount: Double
3、buyDate: Date
想按日期分组:
@SectionedFetchRequest(
sectionIdentifier: \CurrencyRecord.buyDate,
sortDescriptors: [
SortDescriptor(\CurrencyRecord.buyDate, order: .reverse),
SortDescriptor(\CurrencyRecord.currency)
],
animation: .default
)
private var records: SectionedFetchResults<Date, CurrencyRecord>
然后在 View 中使用:
List {
ForEach(records) { section in
Section(header: Text(section.id.formatted(date: .abbreviated, time: .omitted))) {
ForEach(section) { record in
HStack {
Text(record.currency)
Spacer()
Text("\(record.amount, specifier: "%.2f")")
}
}
}
}
}
注意事项
1、sectionIdentifier 的属性必须是 Hashable。
2、如果是 Date 类型,考虑按“日”分组(忽略时分秒),否则每条记录都是一个 Section,可以通过扩展 Date 做标准化:
extension Date {
var startOfDay: Date {
Calendar.current.startOfDay(for: self)
}
}
然后建一个 transient 属性 buyDay 映射为 startOfDay。
3、SectionedFetchRequest 仅适用于 iOS 15+。