【问题标题】:shape data from core data into plottable format将核心数据中的数据整形为可绘图格式
【发布时间】:2021-11-06 07:42:12
【问题描述】:

我有一个关于在 SwiftUI 中根据核心数据中的数据绘制图表的概念性问题。 假设我正在构建一个待办事项列表应用程序,并且我在核心数据中有一个待办事项实体。该实体具有属性 name 和 finishDate(待办事项被标记为完成的日期)。

要绘制这两个变量,我需要一个包含每一天的变量和一个包含每个特定日期完成任务数的变量。

有谁知道我将如何有效地创建这些数据?我知道我可以获取 todo 实体数据并选择正确的属性。但是我如何获得每个特定日期完成的任务数?理想情况下不使用 for 循环创建这些变量。

如果有人可以帮助我,将不胜感激。

【问题讨论】:

  • 您需要查看 Core Data 中的关系。坦率地说,我敢打赌有很多 Core Data 教程都使用 ToDo 应用程序作为基础,仅仅是因为它很明显。不管你是否这样做,你至少会熟悉这些问题。
  • 如果数据库管理与核心数据相比,这更多。阅读数据库管理。它更多地是关于您的实体的结构。一旦你有它的结构,它是关于排序描述符、谓词,甚至可能是部分,你可以有每日部分。查找 WWDC21 CoreData 视频,我认为关于并发的视频谈到了分段获取请求

标签: xcode plot core-data swiftui


【解决方案1】:

这很容易使用 CoreData + SwiftUI。

以下代码适用于 iOS15+,但您可以使用 NSFetchedResultsControllerNSFetchRequest / @FetchRequest 执行相同操作,然后将其分组。但要保持实时,需要付出一些努力。

此外,下面的代码旨在与 CoreData 项目的标准 Apple 代码一起使用。我在PersistenceController 中唯一更改的是为timestamp 设置随机日期

newItem.timestamp = Date().addingTimeInterval(60*60*24*Double(Int.random(in: -10...10)))

这是一个简单的图表

import SwiftUI

@available(iOS 15.0, *)
struct DayChart: View {
    @SectionedFetchRequest(entity: Item.entity(), sectionIdentifier: \.completionDate, sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)], predicate: nil, animation: Animation.linear)
    var sections: SectionedFetchResults<String, Item>
    @State var maxCount: Int = 1
    let spacing: CGFloat = 3
    var body: some View {
        VStack{
            GeometryReader{ geo in
                HStack(alignment: .bottom, spacing: spacing){
                    ForEach(sections){section in
                        VStack{
                            Text(section.count.description)
                            Rectangle()
                                .foregroundColor(.blue)
                                .onAppear(){
                                    maxCount = max(maxCount,section.count)
                                    
                                }
                            Text(section.id.description).minimumScaleFactor(0.5)
                            .lineLimit(2)
                        }.frame(width: (geo.size.width/CGFloat(sections.count) - spacing),height: geo.size.height * CGFloat(CGFloat(section.count)/CGFloat(maxCount)))
                    }
                }
            }
        }.padding(.leading, spacing)
    }
}

@available(iOS 15.0, *)
struct DayChart_Previews: PreviewProvider {
    static var previews: some View {
        DayChart().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
    }
}
extension Item{
    //This is the variable that determines your section/column/completion date
    @objc
    var completionDate: String{
                    
        if self.timestamp != nil{
            let dateFormatter: DateFormatter = DateFormatter()
            dateFormatter.dateFormat = "dd\nMMM"
            return dateFormatter.string(from: self.timestamp!)
             
        }else{
            return ""
        }
    }
}

【讨论】:

【解决方案2】:

我将从星期几的属性开始(您可以从您用于完成日期的Date() 值派生该属性)。然后,您可以使用计数获取请求 (Cocoa Core Data efficient way to count entities),或 group-by 和 NSDictionaryResultTypehttps://www.cocoanetics.com/2017/04/group-by-count-and-sum-in-coredata/ 上的广泛代码示例)。 group-by 方法将为您提供一个如下所示的字典(来自 Cocoanetics 文章):

[
   {
      "count": 111,
      "col": "One"
   },
   {
      "count": 222,
      "col": "Two"
   }
]

我相信,但不确定,您必须计算/存储星期几值作为这些分组方法起作用的属性。

【讨论】:

    猜你喜欢
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多