如何在SwiftUI中按日期对核心数据项进行分组? [英] How to group core data items by date in SwiftUI?

查看:249
本文介绍了如何在SwiftUI中按日期对核心数据项进行分组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的iOS应用程序具有以下功能:

What I have in my iOS app is:

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个实体:待办事项。模块:当前产品模块。 Codegen:类定义。
此实体具有 2个属性:标题(字符串),日期(日期)

I am using Core Data and have 1 Entity: Todo. Module: Current Product Module. Codegen: Class Definition. This entity has 2 attributes: title (String), date (Date).

ContentView.swift
显示列表。

ContentView.swift Displays the list.

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
在此视图中,我添加新项目。

TodoAddView.swift In this view I add new item.

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,但是它不适用于SwiftUI中的.sheet。当我打开.sheet(点击添加后)时,应用程序崩溃并出现错误:

I have tried this: I have searched for some examples. One looked good: How to properly group a list fetched from CoreData by date? and I have used the update function and ForEach from there, but it doesn't work with .sheet in SwiftUI. When I open the .sheet (after tapping Add) the app crashes with an error:


线程1:异常:试图创建两个单元格的动画

Thread 1: Exception: "Attempt to create two animations for cell"

如何解决?还是有按日期对核心数据进行分组的另一种方法?有人告诉我应该将分组添加到数据模型中。并稍后在UI中显示。我不知道从哪里开始。

How to fix it? Or is there another way of grouping core data by date? I have been told that I should add grouping to my data model. And just show it later in UI. I don't know where to start.

另一个猜测是,我也许可以编辑我的@FetchRequest代码以在其中添加分组。但是我几天没有运气在寻找解决方案。
我知道Core Data中有一个setPropertiesToGroupBy,但是我不知道它是否以及如何与@FetchRequest和SwiftUI一起使用。

Another guess is that I maybe could edit my @FetchRequest code to add grouping there. But I am searching for a solution few days without luck. I know there is a setPropertiesToGroupBy in Core Data, but I don't know if and how it works with @FetchRequest and SwiftUI.

猜测:是否可以使用Dictionary(grouping:attributeName)根据SwiftUI中的属性将CoreData Entity实例分组?
分组数组看起来非常简单: https://www.hackingwithswift.com/example-code/language/how-to-group-arrays-using-dictionaries ,但是我不知道它是否以及如何与Core Data和@FetchRequest一起使用。

Another guess: Is it possible to use Dictionary(grouping: attributeName) to group CoreData Entity instances in SwiftUI based on their attributes? Grouping arrays looks so easy: https://www.hackingwithswift.com/example-code/language/how-to-group-arrays-using-dictionaries , but I don't know if and how it works with Core Data and @FetchRequest.

推荐答案

我只是自己进入SwiftUI,所以这可能是一个误解,但我认为问题在于 update 函数不稳定,因为它不能保证每次都以相同的顺序返回组。因此,添加新项目时,SwiftUI会感到困惑。我发现通过对数组进行特殊排序可以避免错误:

I'm just getting into SwiftUI myself, so this might be a misunderstanding, but I think the issue is that the update function is unstable, in the sense that it does not guarantee to return the groups in the same order each time. SwiftUI consequently gets confused when new items are added. I found that the errors were avoided by specifically sorting the array:

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

这篇关于如何在SwiftUI中按日期对核心数据项进行分组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆