按忽略年份的最近日期对 NSFetchedResultsController 进行排序

Sort NSFetchedResultsController by closest date ignoring year

我正在使用 Core Data 和 NSFetchedResultsController 在 table 视图中显示日期。获取时,我希望这些日期对象按最接近今天的 month/day 排序,同时忽略年份,最好(如果可能的话)不必将获取的结果存储在数组中并被迫对其执行单独的排序操作大批。这是基本的想法,剩下的就是上下文。

我的 NSManagedObject 子类 Date 有 2 个属性:

Date.date -> 1986-02-06 08:00:00 +0000 // the stored date of type Date
Date.equalizedDate -> 02/06 // computed from date ignoring year of type String

如果我在获取的结果控制器上使用 NSSortDescriptor(key: "date", ascending: true),则 table 视图中的日期按年份排序(不是我想要的):

Date.date 1978-06-23 07:00:00 +0000 // 1978 = #1
Date.date 1986-02-06 08:00:00 +0000 // 1986 = #2
Date.date 1991-07-26 07:00:00 +0000 // 1991 = #3

如果我使用 NSSortDescriptor(key: "equalizedDate", ascending: true) 我可以通过忽略年份并显示正确的提升来更接近一步,但它没有与今天的日期进行比较:

Date.date 1986-02-06 08:00:00 +0000 // 02/06 = #1 (February 6th)
Date.date 1978-06-23 07:00:00 +0000 // 06/23 = #2 (June 23rd)
Date.date 1991-07-26 07:00:00 +0000 // 07/26 = #3 (July 26th)

如果今天是4月5日,那么我希望抓取的结果显示如下:

                                       // Today is April 5th
Date.date 1978-06-23 07:00:00 +0000 // 06/23 = #1 (June 23rd)
Date.date 1991-07-26 07:00:00 +0000 // 07/26 = #2 (July 26th)
Date.date 1986-02-06 08:00:00 +0000 // 02/06 = #3 (February 6th)

目前,我实现此目的的唯一方法是将获取的结果控制器结果存储在数组中,对数组执行比较,并使用数组而不是我的获取结果控制器作为我的数据源table 查看行和单元格:

// fetchedResults = [Date] <- stored Date objects from fetch
for fetchedDate in fetchedResults {
    // formatDateIntoString changes 2015-10-26 05:43:22 +0000 into 10/26
    if fetchedDate.equalizedDate < NSDate().formatDateIntoString() {
        fetchedResults.removeAtIndex(0)
        fetchedResults.append(fetchedDate)
    } else {
        break
    }
}
return fetchedResults

我宁愿省略这个额外的逻辑层,因为它不仅消除了获取结果控制器的整个性能目的,而且在实现滑动删除时还会给我带来不稳定的麻烦和错误的索引路径().我知道比较器和选择器不适用于获取的结果控制器。

有什么办法可以解决这个问题吗?

如果您不关心部分,一个简单的方法是保持对 equalizedDate 的排序(如果您有很多日期,请确保将该属性设置为索引)。您可能还想考虑将其更改为整数而不是字符串。

数组将从 01/01 到 12/31 排序。

然后,您可以在初始提取后进行另一次快速提取,以找到最接近今天日期的对象。

该对象现在成为您的参考点(或 startingIndex)。

在您的 FRC 委托中,只需使用起始索引作为偏移量。

因此,当被要求 return 索引 0 处的对象时,您 return 一个基于起始索引的值。

类似...

NSUInteger actualIndex = (index + startingIndex) % count;

如果使用节,会稍微复杂一些,但不会太多。

这样,您不必为排序做任何特别的事情。当您的应用程序中的日期发生变化时,也很容易更改。

我认为更简单的解决方案是简单地修改您的 equalizedDate 属性,如下所示:

首先,把它变成瞬态 属性.

其次,让它根据当前日期动态运行。你可以把这个属性做的很简单,但是需要写更多的代码来解释它,或者你可以尝试return一些你可以直接使用的东西。

一个简单的解决方案是 return 只是 从今天的日期 的偏移量(从 0 到 365 的数字)。您必须根据此数字和今天的日期向 return 添加正确的日期字符串(或日期)功能。

IMO 更好的解决方案是 return 具有 正确标准化年份 的日期。您可以将当前日期和未来日期设置为当前年份,将所有过去的日期设置为下一年,也将产生 365 (366) 个日期。

您现在可以轻松地按瞬态 属性 排序,甚至可以将其用于分段。