2015-10-26 72 views
2

我正在使用核心数据和NSFetchedResultsController在表视图中显示日期。在获取时,我希望这些日期对象按照即将到来的月份/日期排序,直到今天忽略年份,最好(如果可能),而不必将获取的结果存储在数组中,并被迫对该数组执行单独的排序操作。这是基本的想法,其余的是上下文。按最近日期排序NSFetchedResultsController忽略年份

我的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),然后在表视图中的日期由今年(不是我想要的)排序

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) 

目前,由我来完成的唯一途径,这是通过存储所取出的结果控制器导致的阵列,在执行到阵列上的比较,以及使用我的读取的结果控制器的阵列,而不是用于我的表视图行和单元格的数据源:

// 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 

我宁愿省略这个额外的逻辑层,因为它不仅消除了获取结果控制器的完整性能,而且在执行轻扫删除操作时(link for reference)也给我带来了不可思议的麻烦和错误的索引路径。我知道比较器和选择器不适用于提取结果控制器。

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

+0

是否在其他地方使用了'equalizedDate'?如果解决这个问题更容易,是否可以为这个领域使用不​​同的值(或不同的类型)? –

回答

1

我认为,一个更简单的解决方案是简单地修改你的equalizedDate属性如下:

首先,使之成为一个短暂财产。

其次,根据当前日期使其动态行为。你可以使这个属性非常简单,但是需要编写更多的代码来解释它,或者你可以尝试返回可以直接使用的东西。

一个简单的解决方案是从今天的日期(从0到365的数字)仅返回偏移量。您必须添加功能才能返回基于此编号和今天日期的正确日期字符串(或日期)。

国际海事组织更好的解决方案是返回日期与正确标准化年。您可以将当前和未来日期设置为当前年份,将过去的所有日期设置为下一年,也会导致365(366)个日期。

您现在可以轻松地通过瞬态属性进行排序,甚至可以将它用于分段。

+0

如果有“相对较小”的数据量,这是最好的方法。但是,使用这种方法会阻止在sql级别进行排序,这对于非常大的数据集可能会产生问题。 –

+0

@JodyHagins我的数据集是0 - 300之间的任何地方,所以这个答案更相关,但我给了你一个正确的解决方案upvote更大的集。作为一个附注,有多少被抓取的对象会被认为是“相对较小”和“较大”数据集之间的分隔线(假设没有关系和一些属性)? – Aaron

+0

这将取决于您自己的性能分析以及我们应用程序的目标设备,但是我会说,直到您进入成千上万的时候,使用此解决方案才会完美无缺。请记住,每个对象都将被加载并存入内存以访问数据。您可以通过只抓取您需要的属性来优化它,但我不担心这样一个小数据集。 –

2

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

该阵列将从01/01到12/31排序。

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

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

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

因此,当要求返回索引0处的对象时,您会返回基于起始索引的值。

像...

NSUInteger actualIndex = (index + startingIndex) % count; 

这是一个有点复杂,如果你正在使用的部分,但并不多。

这样,您不必为排序做任何特殊的事情。在应用程序中更改日期时也很容易进行更改。

+0

我认为你不是指“FRC委托”,而是表视图数据源。 – Mundi