使用 NSFetchedResultsController 按日期(包括 nil)排序
在我的 NSFetchedResultsController 中,我设置了一个 sortDescriptor,它根据托管对象的日期属性进行排序。我遇到的问题(以及根据谷歌的其他几个问题)是 nil 值在日期范围的最早末端而不是最新末端排序。我希望我的列表按最早、更早、现在、稍后、最新、零排序。据我了解,这种排序是在 SQLite 的数据库级别完成的,因此我无法构建自己的比较:方法来提供我想要的排序。
我不想在内存中手动排序,因为我将不得不放弃 NSFetchedResultsController 的所有好处。我无法进行复合排序,因为sectionNameKeyPaths 与日期范围紧密耦合。我可以编写一个例程来重定向 indexPath 请求,以便将结果控制器中的第 0 部分映射到 tableView 的最后一部分,但我担心这会增加大量开销,严重增加代码的复杂性,并且非常,非常容易出错。
我正在考虑的最新想法是将所有零日期映射到 NSDate 支持的最远的未来日期。我的左脑讨厌这个想法,因为它感觉更像是一种黑客行为。它还需要一些工作来实现,因为我在应用程序中处理日期的方式中大量检查了零因素。在没有先检查更好的选择之前,我不想走这条路。谁能想出更好的方法来解决这个问题吗?
更新
解决此问题的一个可能更好的方法是切换到二进制持久存储。根据我在文档中读到的内容,排序是在 Objective-C 中使用二进制持久存储完成的,因此我可以提供自己的比较方法来进行日期排序。我对这种方法有两个担忧。首先,迁移到二进制存储后我会看到什么样的性能影响?其次,在应用程序更新中推出此更改有多困难?
In my NSFetchedResultsController, I set a sortDescriptor that sorts based on the date property of my managed objects. The problem that I have encountered (along with several others according to Google) is that nil values are sorted at the earliest end rather than the latest end of the date spectrum. I want my list to be sorted earliest, earlier, now, later, latest, nil. As I understand it, this sorting is done at the database level in SQLite and so I cannot construct my own compare: method to provide the sorting I want.
I don't want to manually sort in memory, because I would have to give up all of the benefits of NSFetchedResultsController. I can't do compound sorting because the sectionNameKeyPaths are tightly coupled to the date ranges. I could write a routine that redirects indexPath requests so that section 0 in the results controller gets mapped to the last section of the tableView, but I fear that would add a lot of overhead, severely increase the complexity of my code, and be very, very error-prone.
The latest idea that I am considering is to map all nil dates to the furthest future date that NSDate supports. My left brain hates this idea, as it feels more like a hack. It will also take a bit of work to implement, since checking for nil factors heavily into how I process dates in my app. I don't want to go this route without first checking for better options. Can anyone think of a better way to get around this problem?
Update
A possible better way to get around this problem would be to switch to a binary persistent store. From what I have read in the documentation, sorting is done in Objective-C with the binary persistent store, so I could supply my own compare method for the date sorting. I have two concerns with this approach. First, what kind of performance hit am I going to see by moving to a binary store? Second, how difficult is it going to be to roll out this change in an app update?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不知道是否可以更改 NSFetchedResultsController 中零日期的排序位置。但是,我确实有一个类似于您将零日期更改为未来时间的“黑客”的建议。具体来说,我将为您的实体创建一个新的瞬态属性,该属性返回修改日期。基本上,该属性的自定义 getter 将检索日期,然后检查它是否为零。如果是这样,它将返回 NSDate 支持的最新未来日期。这将允许 NSFetchedResultsController 按照您想要的方式对结果进行排序。
使用瞬态属性是创建包含使用某人姓氏的第一个字母的部分的列表(如联系人应用程序)的方式。 此处描述了执行此操作的方法 。
例如:
}
I don't know if it is possible to change where the nil dates are sorted to in the NSFetchedResultsController. However, I do have a suggestion along the lines of your "hack" of changing nil dates to a future time. Specifically, I would create a new transient property for your entity that returns a modified date. Basically, the custom getter for that property would retrieve the date and then check if it is nil. If so, it would return the latest future date that NSDate supports. This would allow the NSFetchedResultsController to sort the results in the way you want.
Using transient properties is how lists with sections using the first letter of a person's last name (a la the Contacts App) are created. A method for doing that is described here.
For example:
}
我决定采用“hack”修复,因为我不想承担使用二进制存储将整个对象图加载到内存中的开销。当用户未设置日期时,我不会存储 nil,而是存储“noDate”类方法的结果。
I decided to go with the "hack" fix, because I didn't want to incur the overhead of having the entire object graph loaded in memory that comes with using the binary store. Instead of storing nil when the user doesn't set a date, I store the result of a "noDate" class method.