按 Month/Year 对 FechedResults 进行分组以显示包含部分的 swiftui 列表
Grouping FechedResults by Month/Year to display a swiftui list with sections
我有一个包含日期属性的核心数据实体 (LogEntry)。我正在尝试将视图迁移到 SwiftUI,并且该视图必须显示按年月分组(并按时间顺序排序)的所有日志条目,如下所示:
2017 年 6 月
- 日志条目 1(6 月 10 日)
- 日志条目 2(6 月 16 日)
- 日志条目 3(6 月 17 日)
2017 年 7 月
- 日志条目 1(7 月 1 日)
- 日志条目 2(7 月 3 日)
- 等等
我已经能够使用此代码实现所需的分组:
func group(_ result : FetchedResults<LogEntry>) -> [[LogEntry]] {
return Dictionary(grouping: result){ (element : LogEntry) in
sectionDateFormatter.string(from: element.date as Date)
}.values.map{[=11=]}
}
var body: some View {
NavigationView {
List {
ForEach(group(logEntries), id: \.self) { (section: [LogEntry]) in //Works but not ordered
Section(header: Text( self.sectionDateFormatter.string(from: section[0].date as Date))) {
ForEach(section, id: \.self) { logEntry in
HStack {
Text("\(self.logDateFormatter.string(from: logEntry.date as Date))")
Spacer()
Text("\(logEntry.total) m").font(.subheadline)
}
}
}
}.id(logEntries.count)
}
.listStyle(PlainListStyle())
}
}
一段时间以来,我一直在尝试添加排序,但似乎无法在 SwiftUI 的上下文中找到正确的方法。
我试过这个:
func update(_ result : FetchedResults<LogEntry>)-> [[LogEntry]]{
return Dictionary(grouping: result){ (element : LogEntry) in
sectionDateFormatter.string(from: element.date as Date)
}.values.sorted() { [=12=][0].date! < [0].date! }
}
...但是我收到“没有更多上下文的表达式类型不明确”错误并且无法编译。
我也试过这个:
func groupedByYearMonth(_ result: FetchedResults<LogEntry>) -> [Date: [LogEntry]] {
let empty: [Date: [LogEntry]] = [:]
return logEntries.reduce(into: empty) { acc, cur in
let components = Calendar.current.dateComponents([.year, .month], from: cur.date as Date)
let date = Calendar.current.date(from: components)!
let existing = acc[date] ?? []
acc[date] = existing + [cur]
}
}
...但在这种情况下,我不知道如何调整 SwiftUI 列表 ForEach 以使用它。
如有指点,将不胜感激!
如果您在可以正确排序的临时字典中使用不同的键,则可以对获取的结果进行排序。因此,对于函数中使用的 DateFormatter,我将格式设置为“yyyy-MM”。
请注意,我首先对函数的输入进行排序,但如果获取的结果已经按照我推荐的 date
排序,则不需要此步骤。
func group(_ result : FetchedResults<LogEntry>) -> [[LogEntry]] {
let sorted = result.sorted { [=10=].date < .date }
return Dictionary(grouping: sorted) { (element : LogEntry) in
dictionaryDateFormatter.string(from: element.date as Date)
}.sorted { [=10=].key < .key }.map(\.value)
}
我有一个包含日期属性的核心数据实体 (LogEntry)。我正在尝试将视图迁移到 SwiftUI,并且该视图必须显示按年月分组(并按时间顺序排序)的所有日志条目,如下所示:
2017 年 6 月
- 日志条目 1(6 月 10 日)
- 日志条目 2(6 月 16 日)
- 日志条目 3(6 月 17 日)
2017 年 7 月
- 日志条目 1(7 月 1 日)
- 日志条目 2(7 月 3 日)
- 等等
我已经能够使用此代码实现所需的分组:
func group(_ result : FetchedResults<LogEntry>) -> [[LogEntry]] {
return Dictionary(grouping: result){ (element : LogEntry) in
sectionDateFormatter.string(from: element.date as Date)
}.values.map{[=11=]}
}
var body: some View {
NavigationView {
List {
ForEach(group(logEntries), id: \.self) { (section: [LogEntry]) in //Works but not ordered
Section(header: Text( self.sectionDateFormatter.string(from: section[0].date as Date))) {
ForEach(section, id: \.self) { logEntry in
HStack {
Text("\(self.logDateFormatter.string(from: logEntry.date as Date))")
Spacer()
Text("\(logEntry.total) m").font(.subheadline)
}
}
}
}.id(logEntries.count)
}
.listStyle(PlainListStyle())
}
}
一段时间以来,我一直在尝试添加排序,但似乎无法在 SwiftUI 的上下文中找到正确的方法。
我试过这个:
func update(_ result : FetchedResults<LogEntry>)-> [[LogEntry]]{
return Dictionary(grouping: result){ (element : LogEntry) in
sectionDateFormatter.string(from: element.date as Date)
}.values.sorted() { [=12=][0].date! < [0].date! }
}
...但是我收到“没有更多上下文的表达式类型不明确”错误并且无法编译。
我也试过这个:
func groupedByYearMonth(_ result: FetchedResults<LogEntry>) -> [Date: [LogEntry]] {
let empty: [Date: [LogEntry]] = [:]
return logEntries.reduce(into: empty) { acc, cur in
let components = Calendar.current.dateComponents([.year, .month], from: cur.date as Date)
let date = Calendar.current.date(from: components)!
let existing = acc[date] ?? []
acc[date] = existing + [cur]
}
}
...但在这种情况下,我不知道如何调整 SwiftUI 列表 ForEach 以使用它。
如有指点,将不胜感激!
如果您在可以正确排序的临时字典中使用不同的键,则可以对获取的结果进行排序。因此,对于函数中使用的 DateFormatter,我将格式设置为“yyyy-MM”。
请注意,我首先对函数的输入进行排序,但如果获取的结果已经按照我推荐的 date
排序,则不需要此步骤。
func group(_ result : FetchedResults<LogEntry>) -> [[LogEntry]] {
let sorted = result.sorted { [=10=].date < .date }
return Dictionary(grouping: sorted) { (element : LogEntry) in
dictionaryDateFormatter.string(from: element.date as Date)
}.sorted { [=10=].key < .key }.map(\.value)
}