Как правильно сгруппировать записи CoreData по категориям в SwiftUI? - PullRequest
0 голосов
/ 26 марта 2020

Я использую CoreData. У меня есть:

  • 1 Объект: Todo
  • 3 атрибута: категория (строка), дата (дата), заголовок (строка).
  • Модуль: текущий продукт Модуль
  • Codegen: определение класса

Я хотел бы создать простое приложение ToDo, которое выглядит следующим образом:

To do items

Category
1. 3/26/20 To do item 1
2. 3/26/20 To do item 2

Category
1. 3/26/20 To do item 3
2. 3/27/20 To do item 4

Я знаю, что есть похожие вопросы, но я не нашел ответа о том, как все настроить с помощью CoreData и SwiftUI.

Большая часть кода выполнена. Включая добавление элементов, сохранение в CoreData, удаление элементов.

ContentView.swift Здесь я отображаю список дел. Я добавил комментарии к проблематичным c частям.

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>

    @State private var show_modal: Bool = false

//  let dictionary = Dictionary(grouping: Todo) { $0.category }

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

    var body: some View {
        NavigationView {
            List {

                // Here I should sort by category
                ForEach(self.todos, id: \.title) { todo in

                    // Here I should write category name instead of static text
                    Section(header: Text("Category")) {
                        ForEach(Array(self.todos.enumerated()), id: \.element) {(i, todo) in

                            NavigationLink(destination: TodoDetailsView(todo: todo)) {
                                HStack {
                                    Text("\(i+1). ")
                                    Text("\(todo.date ?? Date(), formatter: self.dateFormatter)")
                                    Text(todo.title ?? "")
                                }
                            }
                        }
                    }
                }

            }
            .navigationBarTitle(Text("To do items"))
            .navigationBarItems(
                trailing:
                Button(action: {
                    self.show_modal = true
                }) {
                    Text("Add")
                }.sheet(isPresented: self.$show_modal) {
                    TodoAddView().environment(\.managedObjectContext, self.moc)
                }
            )
                .listStyle(GroupedListStyle())
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        return ContentView().environment(\.managedObjectContext, context)
    }
}

TodoAddView.swift Здесь я добавляю новые элементы и сохраняю их в CoreData. Это работает нормально.

import SwiftUI

struct TodoAddView: View {

    @Environment(\.presentationMode) var presentationMode
    @Environment(\.managedObjectContext) var moc

    static let dateFormat: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        return formatter
    }()

    @State private var showDatePicker = false
    @State private var title = ""
    @State private var category = ""
    @State private var date : Date = Date()

    var body: some View {
        NavigationView {

            VStack {
                HStack {
                    Button(action: {
                        self.showDatePicker.toggle()
                    }) {
                        Text("\(date, formatter: Self.dateFormat)")
                    }

                    Spacer()
                }

                if self.showDatePicker {
                    DatePicker(
                        selection: $date,
                        displayedComponents: .date,
                        label: { Text("Date") }
                    )
                        .labelsHidden()
                }

                TextField("title", text: $title)
                TextField("category", text: $category)

                Spacer()

            }
            .padding()
            .navigationBarTitle(Text("Add to do item"))
            .navigationBarItems(
                leading:
                Button(action: {
                    self.presentationMode.wrappedValue.dismiss()
                }) {
                    Text("Cancel")
                },

                trailing:
                Button(action: {

                    let todo = Todo(context: self.moc)
                    todo.date = self.date
                    todo.title = self.title
                    todo.category = self.category

                    do {
                        try self.moc.save()
                    }catch{
                        print(error)
                    }

                    self.presentationMode.wrappedValue.dismiss()
                }) {
                    Text("Done")
                }
            )
        }
    }
}

struct TodoAddView_Previews: PreviewProvider {
    static var previews: some View {
        TodoAddView()
    }
}

TodoDetailsView.swift Здесь я отображаю детали каждого элемента и могу удалить элемент оттуда. Это тоже хорошо работает.

import SwiftUI

struct TodoDetailsView: View {

    @Environment(\.managedObjectContext) var moc
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    var todo: Todo

    static let dateFormat: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        return formatter
    }()

    @State private var showDatePicker = false
    @State private var newDate : Date = Date()
    @State private var newTitle = ""
    @State private var newCategory = ""

    var body: some View {
        ScrollView {

            VStack {
                HStack {
                    Button(action: {
                        self.showDatePicker.toggle()
                    }) {
                        Text("\(newDate, formatter: Self.dateFormat)")
                    }

                    Spacer()
                }

                if self.showDatePicker {
                    DatePicker(
                        selection: $newDate,
                        displayedComponents: .date,
                        label: { Text("Date") }
                    )
                        .labelsHidden()
                }

                TextField("title", text: $newTitle, onCommit: {
                    self.todo.title = self.newTitle
                    try? self.moc.save()
                }
                )

                TextField("category", text: $newCategory, onCommit: {
                    self.todo.category = self.newCategory
                    try? self.moc.save()
                }
                )

                Spacer()

            }
            .padding()
            .navigationBarTitle(Text("Details"))
            .navigationBarItems(
                trailing:
                Button(action: {
                    self.moc.delete(self.todo)
                    do {
                        try self.moc.save()
                        self.presentationMode.wrappedValue.dismiss()
                    }catch{
                        print(error)
                    }
                }) {
                    Text("Delete")
                        .foregroundColor(.red)
                }
            )
        }
        .onAppear {
            self.newDate = self.todo.date ?? Date()
            self.newTitle = self.todo.title ?? ""
            self.newCategory = self.todo.category ?? ""
        }
        .onDisappear {
            self.todo.date = self.newDate
            self.todo.title = self.newTitle
            self.todo.category = self.newCategory
            try? self.moc.save()
        }
    }
}

struct TodoDetailsView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        let todo = Todo.init(context: context)
        todo.date = Date()
        todo.title = "to do item"
        return TodoDetailsView(todo: todo).environment(\.managedObjectContext, context)
    }
}

Не знаю, как правильно сгруппировать элементы, например, по категориям. Как это сделать с помощью Core Data? Я предполагаю, что мне нужно изменить Codegen моей организации и добавить расширение для группировки записей. Например, что-то вроде этого:

let dictionary = Dictionary(grouping: Todo) { $0.category }

Но должно ли это быть Ручное / Нет или Категория / Расширение? И где и какой код использовать? Я знаю, как создать Подкласс.

И позже я, вероятно, мог бы сослаться на этот словарь в ForEach в моем ContentView. Но не знаю, как именно.

Если мои предположения неверны, пожалуйста, поправьте меня. Заранее спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...