在 NSFetchedResultsController 中使用 sectionNameKeyPath 时的顺序

Posted

技术标签:

【中文标题】在 NSFetchedResultsController 中使用 sectionNameKeyPath 时的顺序【英文标题】:Order when using sectionNameKeyPath in NSFetchedResultsController 【发布时间】:2014-07-28 14:59:21 【问题描述】:

在 Core Data 中,我有一对多的关系——每个布局都有很多行:

我正在尝试通过分组布局在表格视图中显示数据:

Layout Nr 2342 (with orderPosition 1)
    Line 1
    Line 2
    Line …
Layout Nr 2123 (with orderPosition 2)
    Line 1
    Line …
…

我正在使用我这样创建的NSFetchedResultsController

NSEntityDescription *entity = [NSEntityDescription entityForName:@“Line” inManagedObjectContext:managedObjectContext];

NSSortDescriptor *orderPositionDescriptor = [[NSSortDescriptor alloc] initWithKey:@"layout.orderPosition" ascending:YES];

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setSortDescriptors:@[orderPositionDescriptor]];
[fetchRequest setEntity:entity];

NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"section=='my_section'"]];
[fetchRequest setPredicate:predicate];

self.fetchController = [[NSFetchedResultsController alloc]
                                          initWithFetchRequest:fetchRequest
                                          managedObjectContext:managedObjectContext
                                          sectionNameKeyPath:@"layout.groupNumber"
                                          cacheName:nil];

所以我将 fetch 控制器设置为按布局 groupNumber 分组,我还将排序描述符设置为按布局位置排序(每个布局都有自己的位置)。一旦数据被添加到核心数据中,它就会显示在表格视图中。一切正常,直到我尝试更改现有 NSFetchedResultsControllerNSFetchRequest 谓词:

 NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"section=='%@'",section]];
 [self.fetchController.fetchRequest setPredicate:predicate]; 

我在谓词中设置了与已经设置完全相同的部分,并且表格中显示的performFetch之后的数据仍然相同,但是布局(表格部分)在表格中更改了位置并且行显示错误布局(基本上无序)。我发现如果我将第一个排序描述符设置为与 sectionNameKeyPath -“layout.groupNumber”相同,那么即使我更改谓词也一切正常。但显然它不是按我想要实现的 orderPosition 排序的。有什么解决办法吗?任何帮助,将不胜感激。

【问题讨论】:

【参考方案1】:

如果您在表视图中使用部分,并对表视图数据进行排序,请务必了解第一个排序描述符必须与 sectionNameKeyPath 相同。

因此,我建议您将代码更改为类似于此...

    NSEntityDescription *entity = [NSEntityDescription entityForName:@“Line” inManagedObjectContext:managedObjectContext];

//new line of code following...
    NSSortDescriptor *sectionNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"layout.groupNumber" ascending:YES];
    NSSortDescriptor *orderPositionDescriptor = [[NSSortDescriptor alloc] initWithKey:@"layout.orderPosition" ascending:YES];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
//altered line of code following...
    [fetchRequest setSortDescriptors:@[sectionNameDescriptor, orderPositionDescriptor]];
    [fetchRequest setEntity:entity];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"section=='my_section'"]];
    [fetchRequest setPredicate:predicate];

    self.fetchController = [[NSFetchedResultsController alloc]
                                      initWithFetchRequest:fetchRequest
                                      managedObjectContext:managedObjectContext
                                      sectionNameKeyPath:@"layout.groupNumber"
                                      cacheName:nil];

我已经阅读过这方面的内容,但不记得在哪里......所以很抱歉没有文档参考。

这有帮助吗?

【讨论】:

感谢您的帮助,但正如我在问题中已经提到的那样:“如果我将第一个排序描述符设置为与 sectionNameKeyPath - layout.groupNumber 相同,那么即使我更改谓词也一切正常”。如果我的第一个排序顺序描述符是 groupNumber,那么即使 orderPosition 设置为第二个排序描述符,排序也会出错(数据将按组号排序)。 啊抱歉@sash 没有仔细阅读...我再看看 :)【参考方案2】:

我找到了解决问题的方法。因为每个布局组号都有唯一的订单位置,所以解决的办法不是按groupNumber,而是按orderPosition。在这种情况下,我可以将 orderPosition 指定为第一个(也是唯一的)排序描述符。如果其他人有其他更好的解决方案,听到它仍然会很有趣。

NSEntityDescription *entity = [NSEntityDescription entityForName:@“Line” inManagedObjectContext:managedObjectContext];

NSSortDescriptor *orderPositionDescriptor = [[NSSortDescriptor alloc] initWithKey:@"layout.orderPosition" ascending:YES];

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setSortDescriptors:@[orderPositionDescriptor]];
[fetchRequest setEntity:entity];

NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"section=='my_section'"]];
[fetchRequest setPredicate:predicate];

self.fetchController = [[NSFetchedResultsController alloc]
                                          initWithFetchRequest:fetchRequest
                                          managedObjectContext:managedObjectContext
                                          sectionNameKeyPath:@"layout.orderPosition"
                                          cacheName:nil];

【讨论】:

以上是关于在 NSFetchedResultsController 中使用 sectionNameKeyPath 时的顺序的主要内容,如果未能解决你的问题,请参考以下文章

NSFetchedResultsController - 用户驱动的更改

分配的变量引用在哪里,在堆栈中还是在堆中?

NOIP 2015 & SDOI 2016 Round1 & CTSC 2016 & SDOI2016 Round2游记

秋的潇洒在啥?在啥在啥?

上传的数据在云端的怎么查看,保存在啥位置?

在 React 应用程序中在哪里转换数据 - 在 Express 中还是在前端使用 React?