带有 NSFetchedResultsController 的 UITableView:彼此独立地对每个部分进行排序

Posted

技术标签:

【中文标题】带有 NSFetchedResultsController 的 UITableView:彼此独立地对每个部分进行排序【英文标题】:UITableView with NSFetchedResultsController: Sort each section independently of each other 【发布时间】:2013-10-30 23:42:58 【问题描述】:

我正在开发一个核心数据应用程序。我有一个主表,显示具有不同状态的订单:新、已接受、已交付等。

我遇到的问题是我需要按照不同的标准对每个部分进行排序。例如:

新订单需要按最旧的排序。 接受的订单需要按最快的顺序排序,才能在最上面交付。 交付的订单需要按最新排序。

这是我现在获取结果时的代码:

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"CDOrder"];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"orderPosition" ascending:YES],[NSSortDescriptor sortDescriptorWithKey:@"createdDate" ascending:NO]];  

User* user = [User getInstance];
NSDate *TwelveHoursAgo = [NSDate dateWithTimeIntervalSinceNow:-3600 * 12];

request.predicate = [NSPredicate predicateWithFormat:@"(servicePersonId == %@) AND (createdDate >= %@)", [NSNumber numberWithLong:user.userId], TwelveHoursAgo];
ordersTableViewController.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:super.managedObjectContext sectionNameKeyPath:@"orderPosition" cacheName:nil];

如您所见,这是根据"orderPosition" 制作部分,并按"createdDate" 排序所有订单。但我需要通过"deliverDate"订购某些订单

谢谢

【问题讨论】:

【参考方案1】:

我可以想出两种方法来解决这个问题。

方法一:为每个部分使用单独的 NSFetchedResultsController。 这样您可以为每个部分使用不同的搜索描述符。这会将一些模型细节与您的控制器联系起来,这意味着如果您计划创建一个新的状态类型,您将需要修改您的控制器以及您的模型。

实现这一点的最简单方法是创建一个包含不同 NSFetchedResultsController 的数组。数组中的项目数是节数。但是请注意,这样做可能会导致表格视图中出现空白部分。例如,如果没有任何接受的订单,您可能仍会在 UITableView 中看到 Accepted Orders 部分。

在某些时候,这可能会变得足够复杂,以至于需要将此代码放入其自己的自定义结果控制器中,该控制器在内部管理 NSFetchedResultsController 列表并公开与 NSFetchedResultsController 相似或相同的外部接口。

方法二:在您的模型中添加一个特殊字段作为排序字段,然后自动更新该字段以保持您喜欢的排序顺序。例如,对于状态为“新”您只需将订单日期存储在此字段中。对于具有“已接受”状态的订单,您存储交货日期。对于具有“已交付”状态的订单,您希望存储订单日期,但您希望它处于相反的方向。实现这种反转顺序的最简单方法是存储订单日期乘以 -1。

NSDate 只是一个简单原语的封装,它存储了表示日期和 2001 年 1 月 1 日之间的时间间隔。您可以使用以下代码轻松将该数字乘以 -1:

float interval = [orderDate timeIntervalSinceReferenceDate];
NSDate *reversedDate = [NSDate dateWithTimeIntervalSinceReferenceDate:(interval * -1)];

使用上面的代码,订单日期 2013-10-31 02:03:20 会导致日期反转为 1988-03-03 21:56:48。

如果您还没有这样做,您需要通过为 Order 实体实现一个自定义类,并为订单状态和所涉及的日期编写自定义设置器来更改此字段它依赖的字段发生变化。

第二种方法看起来很不自然,需要进行非规范化,但可能是更好的解决方案,具体取决于您的应用程序以及您希望该应用程序在未来如何变化。

【讨论】:

这两种方法听起来都很有趣。方法 2 听起来是最简单的。但是方法 1 也可以帮助我解决另一个问题。客户希望节标题始终显示,即使它们是空的。所以你的描述听起来也可以帮助解决这些问题。我会给他们两个都试一试,如果我成功了,我会回来选择你的答案是正确的。谢谢! 方法 2 效果很好!反向日期的好把戏。谢谢! 方法一非常有用。当用户开始在 UISearchBar 中搜索时,我这样做是为了交换搜索结果 FRC 和普通项目 FRC。干得好!

以上是关于带有 NSFetchedResultsController 的 UITableView:彼此独立地对每个部分进行排序的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 3 中难以配置 NSFetchedResultsController

如何根据计算的属性过滤来自 NSFetchedResultsController 的结果?

为啥 beginUpdates/endUpdates 会重置表视图位置以及如何阻止它这样做?

带有多个链接的 NSAttributedString 的 UILabel,带有行限制,显示尾部截断,带有未见文本的 NSBackgroundColorAttributeName

使用带有 uuencode 的“sendmail”发送邮件,并带有主题

带有和不带有聚合的 sql 查询