【问题标题】:Sorting by dates (including nil) with NSFetchedResultsController使用 NSFetchedResultsController 按日期(包括 nil)排序
【发布时间】:2011-02-01 09:30:38
【问题描述】:

在我的 NSFetchedResultsController 中,我设置了一个 sortDescriptor,它根据我的托管对象的日期属性进行排序。我遇到的问题(连同其他几个根据谷歌)是 nil 值在日期范围的最早端而不是最晚端排序。我希望我的列表最早、更早、现在、稍后、最新、无排序。据我了解,这种排序是在 SQLite 中的数据库级别完成的,因此我无法构建自己的 compare: 方法来提供我想要的排序。

我不想在内存中手动排序,因为我将不得不放弃 NSFetchedResultsController 的所有好处。我不能进行复合排序,因为 sectionNameKeyPaths 与日期范围紧密耦合。我可以编写一个重定向 indexPath 请求的例程,以便将结果控制器中的第 0 部分映射到 tableView 的最后一部分,但我担心这会增加很多开销,严重增加我的代码的复杂性,并且非常,非常容易出错。

我正在考虑的最新想法是将所有 nil 日期映射到 NSDate 支持的最远未来日期。我的左脑讨厌这个想法,因为它感觉更像是一个黑客。实施起来也需要一些工作,因为在我的应用程序中处理日期的方式中检查 nil 因素很重要。如果不先检查更好的选择,我不想走这条路。谁能想到一个更好的方法来解决这个问题?

更新

解决此问题的更好方法是切换到二进制持久存储。根据我在文档中阅读的内容,排序是在 Objective-C 中使用二进制持久存储完成的,因此我可以为日期排序提供自己的比较方法。我对这种方法有两个担忧。首先,通过迁移到二进制存储,我会看到什么样的性能影响?其次,在应用更新中推出这一变化有多难?

【问题讨论】:

    标签: iphone sorting nsfetchedresultscontroller null


    【解决方案1】:

    我不知道是否可以在 NSFetchedResultsController 中更改 nil 日期的排序位置。但是,我确实有一个建议,类似于您将 nil 日期更改为未来时间的“hack”。具体来说,我将为您的实体创建一个新的瞬态属性,该属性返回修改的日期。基本上,该属性的自定义 getter 将检索日期,然后检查它是否为 nil。如果是这样,它将返回 NSDate 支持的最新未来日期。这将允许 NSFetchedResultsController 以您想要的方式对结果进行排序。

    使用临时属性是创建包含使用个人姓氏的第一个字母的部分的列表(例如联系人应用程序)的方式。描述了这样做的方法here

    例如:

    // THIS ATTRIBUTE GETTER GOES IN YOUR OBJECT MODEL FOR THE 
    // TRANSIENT PROPERTY modifedDate
    - (NSDate *) modifiedDate {
      [self willAccessValueForKey:@"date"];
      NSDate * date = [self date];
      if(date == nil)
        date = // Set as furthest future date.
      [self didAccessValueForKey:@"date"];
      return date;
    

    }

    【讨论】:

    • 据我了解,临时属性可用于 sectionNameKeyPath(事实上,我确实为此使用了临时属性)但不能用于排序描述符,因为排序是由数据库级别的 SQLite,并且数据库中不存在该瞬态属性。如果我对此有误解,请随时纠正我。另一方面,我将使用瞬态属性来“解释”黑客日期并在遇到该特定日期时返回 nil。这将防止我不得不在我的代码的其他部分处理虚假日期。
    • 我的错误。您是正确的,瞬态属性不能用作排序描述符。
    • 如果必须在数据库中进行排序,那么您可以在对象模型中添加一个 hasDate 布尔属性,然后先按该属性排序,然后按日期排序。但是,除了向数据库添加冗余之外,我还假设这是您在原始问题中说要避免的“复合排序”方法。
    • 是的,这就是我所说的复合排序。 sectionNameKeyPath 必须匹配 fetch 请求中第一个排序描述符的排序顺序,因此首先按 hasDate 排序最多会给我的 tableView 中的两个部分。
    【解决方案2】:

    我决定使用“hack”修复,因为我不想承担使用二进制存储将整个对象图加载到内存中的开销。当用户没有设置日期时,我没有存储 nil,而是存储“noDate”类方法的结果。

    【讨论】:

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