在 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 分组,我还将排序描述符设置为按布局位置排序(每个布局都有自己的位置)。一旦数据被添加到核心数据中,它就会显示在表格视图中。一切正常,直到我尝试更改现有 NSFetchedResultsController
的 NSFetchRequest
谓词:
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游记