How to properly group a list fetched from CoreData by date?

橙三吉。 提交于 2020-01-02 16:08:31

问题


For the sake of simplicity lets assume I want to create a simple todo app. I have an entity Todo in my xcdatamodeld with the properties id, title and date, and the following swiftui view (example pictured):

import SwiftUI

struct ContentView: View {

  @Environment(\.managedObjectContext) var moc
  @State private var date = Date()
  @FetchRequest(
    entity: Todo.entity(),
    sortDescriptors: [
      NSSortDescriptor(keyPath: \Todo.date, ascending: true)
    ]
  ) var todos: FetchedResults<Todo>

  var dateFormatter: DateFormatter {
    let formatter = DateFormatter()
    formatter.dateStyle = .short
    return formatter
  }

  var body: some View {
    VStack {
      List {
        ForEach(todos, id: \.self) { todo in
          HStack {
            Text(todo.title ?? "")
            Text("\(todo.date ?? Date(), formatter: self.dateFormatter)")
          }
        }
      }
      Form {
        DatePicker(selection: $date, in: ...Date(), displayedComponents: .date) {
          Text("Datum")
        }
      }
      Button(action: {
        let newTodo = Todo(context: self.moc)
        newTodo.title = String(Int.random(in: 0 ..< 100))
        newTodo.date = self.date
        newTodo.id = UUID()
        try? self.moc.save()
      }, label: {
        Text("Add new todo")
      })
    }
  }
}

The todos are sorted by date upon fetching, and are displayed in a list like this:

I want to group the list based on each todos respective date as such (mockup):

From my understanding this could work with Dictionaries in the init() function, however I couldn't come up with anything remotely useful. Is there an efficient way to group data?


回答1:


You may try the following, It should work in your situation.

  @Environment(\.managedObjectContext) var moc
  @State private var date = Date()
  @FetchRequest(
    entity: Todo.entity(),
    sortDescriptors: [
      NSSortDescriptor(keyPath: \Todo.date, ascending: true)
    ]
  ) var todos: FetchedResults<Todo>

  var dateFormatter: DateFormatter {
    let formatter = DateFormatter()
    formatter.dateStyle = .short
    return formatter
  }

    func update(_ result : FetchedResults<Todo>)-> [[Todo]]{
      return  Dictionary(grouping: result){ (element : Todo)  in
            dateFormatter.string(from: element.date!)
      }.values.map{$0}
    }


  var body: some View {
    VStack {
      List {
        ForEach(update(todos), id: \.self) { (section: [Todo]) in
            Section(header: Text( self.dateFormatter.string(from: section[0].date!))) {
                ForEach(section, id: \.self) { todo in
            HStack {
            Text(todo.title ?? "")
            Text("\(todo.date ?? Date(), formatter: self.dateFormatter)")
            }
            }
          }
        }.id(todos.count)
      }
      Form {
        DatePicker(selection: $date, in: ...Date(), displayedComponents: .date) {
          Text("Datum")
        }
      }
      Button(action: {
        let newTodo = Todo(context: self.moc)
        newTodo.title = String(Int.random(in: 0 ..< 100))
        newTodo.date = self.date
        newTodo.id = UUID()
        try? self.moc.save()
      }, label: {
        Text("Add new todo")
      })
    }
  }


来源:https://stackoverflow.com/questions/59180698/how-to-properly-group-a-list-fetched-from-coredata-by-date

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!