核心数据按年份分组并按日期排序

Posted

技术标签:

【中文标题】核心数据按年份分组并按日期排序【英文标题】:Core Data Group By Year and Sort By Date 【发布时间】:2014-08-21 23:27:51 【问题描述】:

我是 Core Data (ios 7) 的新手,我正在尝试从 FMDB 上的 SQL 切换到 Core Data 获取数据的方式。

我有一个 Entry 实体,其中包含如下数据:

flightDate (date) |  duration (float)
-------------------------------------
  2014-05-21      |      1.0
  2014-08-03      |      2.0
  2013-03-27      |      3.0
  2013-09-16      |      4.0
  2012-12-20      |      5.0
-------------------------------------

我的最终目标是在以 year 作为部分标题的 tableView 中呈现这些数据,并在其下方按时间倒序列出该年份的每个条目。所以数据看起来像这样:

-- 2014 --
Aug 3, 2014     (2.0)
May 21, 2014    (1.0)

-- 2013 --
Sep 16, 2013    (4.0)
Mar 27, 2013    (3.0)

-- 2012 --
Dec 20, 2012    (5.0)

这在 SQL 中很容易实现,但经过数小时的研究,这在 Core Data 中类似于没有麻醉的心脏手术。

最后,我认为拥有这样的 NSMutableDictionary 会很好:


  2014 = 
    <Entry: Aug 3, 2014, 2.0>,
    <Entry: May 21, 2014, 1.0>  
  ,
  2013 = 
    <Entry: Sep 16, 2013, 4.0>,
    <Entry: Mar 27, 2013, 3.0>  
  ,
  2012 = 
    <Entry: Dec 20, 2012, 5.0>
  

...以正确的顺序并准备传递给我的 tableView 代表。如何从 Core Data 对象获取按时间排序和分组的字典数据而不会失去理智?

提前致谢。

【问题讨论】:

你的 NSFetchRequest 目前是什么样子的? 您希望 Core Data 通过什么机制来划分您的结果? 我最初的希望是用数组方法等解析和分组数据,所以我的NSFetchRequest 现在很简单:d.pr/n/kv6f ...我不确定如何使用它. #n00b 【参考方案1】:

使用NSFetchedResultsController。 您可以找到一个根据Apple 的日期将表格分成几部分的工作示例!

【讨论】:

【参考方案2】:
    创建一个 NSFetchRequest。为日期列添加排序描述符。这将使您的行井井有条。 在托管对象上下文中执行获取请求,获取结果 将每个日期分解成组件(使用 like this。 迭代、构建数组,无论您需要做什么,都可以将结果转换成您想要的格式。

1 看起来像这样:

NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Entry"];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"flightDate" ascending:NO];
fetchRequest.sortDescriptors = @[sortDescriptor];

【讨论】:

谢谢!我有 sortDescriptor 工作。好的。我应该使用NSDateComponents而不是NSDateFormatter *format = [NSDateFormatter new]; [format setDateFormat:@"yyyy"];的任何特殊原因? 使用 NSCalendar,您可以执行诸如设置时区之类的操作。此外,dateWithFormat 将返回一个字符串,而不是像 NSDateComponent 中那样的数值。 尽管如果您没有在 CoreData 中存储实际的 NSDate,您将需要使用 DateFormatter 来使用您存储在数据库中的字符串创建日期。 他们是NSDates,是的。 酷。这一切都解决了吗?还有什么需要帮助的吗?【参考方案3】:

核心数据存储NSDates。它们是不透明的、抽象的、时间戳。他们天生没有一年。相同的NSDate 将根据您的时区和日历显示不同的年份。

例如如果格式正确,代表 2001 年 1 月 1 日 GMT 00:01 的 NSDate 在 GMT 手机上将显示为“2001”。它将在 EST 的手机上显示为“2000”。如果手机设置为使用中国日历而不是公历,它将再次显示为非常不同的东西。

我不清楚您究竟为什么会认为这是“SQL 中的简单操作”。可能您以某种方式大大简化了问题?

您可能想要添加一个瞬态属性来返回年份。这将是对NSDateNSCalendar 驱动计算,涉及获取NSDateComponents

您可以将瞬态属性作为sectionNameKeyPath 提供给NSFetchedResultsController

但是请注意语义:除非您检查表中的每一件事,否则您不知道年份是多少。所以你需要获取每一件事。出于性能原因,您可能希望明确告诉您的 fetch 请求不要返回错误*,因此您不会从 Core Data 的自动内存管理中获得任何好处。

(*) Core Data 懒惰地在它的图中获取对象。查询通常返回错误,这些错误是对原始对象的引用,以便可以找到它,但没有实际数据。但是由于对属性的访问是同步的,如果您像填充一样遍历错误,这意味着性能很差——Core Data 无法预测您接下来要访问哪些对象,因此每次访问都是对持久存储的单独访问。

【讨论】:

我的意思是在 SQL 中这很容易,因为我可以在单个 SQL 语句中对数据进行分组、排序和排序。使用 Core Data 需要更多代码。 你说得对,在某种意义上需要更多代码;但是,如果您将年份作为自己的一列,那么需要的代码会少得多——一个获取的结果控制器,这些东西会自动出现在屏幕上,适当的内存管理等等。这只是因为年份是一个瞬态属性事情开始变得有点冗长。

以上是关于核心数据按年份分组并按日期排序的主要内容,如果未能解决你的问题,请参考以下文章

Mongodb:按元素分组并根据条件显示子文档计数并按日期对文档进行排序

iOS 核心数据总和数据按日期、月份年份

SQL选择数据并按日期范围分组数据

NSFetchRequest 分组并按 dateField 计数

SQL: 一般情况按年分组,特殊年份按指定日期分组,SELECT语句怎么写?

s-s-rS 按年份组总计排序