В моем приложении iOS есть:
TO DO ITEMS
To do item 3
24/03/2020
------------
To do item 2
24/03/2020
------------
To do item 1
23/03/2020
------------
Я хотел бы иметь:
TO DO ITEMS
24/03
To do item 3
24/03/2020
------------
To do item 2
24/03/2020
------------
23/03
To do item 1
23/03/2020
------------
==== ===========
Что у меня пока есть:
Я использую Базовые данные и имею 1 Сущность: Todo . Модуль: Модуль текущего продукта. Codegen: определение класса. Этот объект имеет 2 атрибута: заголовок (строка), дата (дата) .
ContentView.swift Отображение списка.
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
var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateStyle = .short
return formatter
}
// func to group items per date. Seemed to work at first, but crashes the app if I try to add new items using .sheet
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 {
NavigationView {
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)
// With this loop there is no crash, but it doesn't group items
//ForEach(Array(todos.enumerated()), id: \.element) {(i, todo) in
// HStack {
// Text(todo.title ?? "")
// Text("\(todo.date ?? Date(), formatter: self.dateFormatter)")
// }
//}
}
}
.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)
}
)
}
}
}
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 В этом представлении я добавляю новый элемент.
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 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)
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
do {
try self.moc.save()
}catch{
print(error)
}
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Done")
}
)
}
}
}
struct TodoAddView_Previews: PreviewProvider {
static var previews: some View {
TodoAddView()
}
}
Я пробовал это: Я искал несколько примеров. Один из них выглядел хорошо: Как правильно сгруппировать список, извлеченный из CoreData по дате? , и я использовал функцию обновления и ForEach оттуда, но она не работает с .sheet в SwiftUI. Когда я открываю .sheet (после нажатия Add), приложение вылетает с ошибкой:
Thread 1: Исключение: «Попытка создать две анимации для ячейки»
Как это исправить? Или есть другой способ группировки основных данных по дате? Мне сказали, что я должен добавить группирование к моей модели данных. И просто показать это позже в пользовательском интерфейсе. Я не знаю с чего начать.
Еще одно предположение состоит в том, что я, возможно, мог бы отредактировать свой код @FetchRequest, чтобы добавить туда группировку. Но я ищу решение несколько дней без удачи. Я знаю, что в Core Data есть setPropertiesToGroupBy, но я не знаю, как и как он работает с @FetchRequest и SwiftUI.
Еще одно предположение: Можно ли использовать словарь (группировка : attributeName) для группировки экземпляров CoreData Entity в SwiftUI на основе их атрибутов? Группировка массивов выглядит так просто: https://www.hackingwithswift.com/example-code/language/how-to-group-arrays-using-dictionaries, но я не знаю, как и как это работает с Core Data и @ FetchRequest.