0

我有一个获取请求“foo”,上面有一个排序描述符(它按降序对整数 16 属性进行排序)。我就这样执行了获取请求:

__block NSArray *results = nil;

[_managedObjectContext performBlockAndWait:
 ^{
     results = [_managedObjectContext executeFetchRequest:<foo> error:nil];
 }];

return results;

当我在 iOS 6+ 下执行此获取请求时,结果按指定/预期排序(反向整数索引顺序)。

但是,当我在 iOS 5.1 下执行时,结果是未排序的!

但是,如果我随后立即将完全相同的排序描述符应用于结果数组:

results = [results sortedArrayUsingDescriptors:<foo>.sortDescriptors];

然后对结果进行正确排序。

有没有其他人遇到过这样的事情?如果有,您发现原因了吗?

谢谢!

卡尔

PS:如果证明相关,这里是“foo”的定义:

-(NSFetchRequest *)fetchRequestForUnparsedStoriesOfStoryListWithId:(id)storyListId
{
    NSPredicate *hasStoryListWithIdPredicate = [NSPredicate predicateWithFormat:@"ANY lists.id = %@", storyListId];
    NSPredicate *isUnparsedStoryOfStoryListWithIdPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[hasStoryListWithIdPredicate, self.isUnparsedPredicate]];

    NSFetchRequest *fetchRequestForUnparsedStoriesOfStoryListWithId = [NSFetchRequest fetchRequestWithEntityName:@"Story"];
    fetchRequestForUnparsedStoriesOfStoryListWithId.predicate = isUnparsedStoryOfStoryListWithIdPredicate;
    fetchRequestForUnparsedStoriesOfStoryListWithId.sortDescriptors = [NSArray arrayWithObject:self.descendingIndexSortDescriptor];

    return fetchRequestForUnparsedStoriesOfStoryListWithId;
}

这是排序描述符的定义:

-(NSSortDescriptor *)descendingIndexSortDescriptor
{
    if (! _descendingIndexSortDescriptor)
    {
        self.descendingIndexSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"index" ascending:NO];
    }

    return _descendingIndexSortDescriptor;
}

PPS:关于此获取的上下文的更多上下文:这发生在应用程序启动时,在 1)服务器信息的后台线程/后台 MOC(具有 NSPrivateQueueConcurrencyType 的嵌套 MOC)解析确定了一些基本属性之后,然后 2) 在后台 MOC 中创建一组 Story 实体,其中包含(除其他外)被排序的索引,然后 3) 保存该背景 MOC 上的更改。只有在这些操作完成后,才会立即执行上述获取请求,并且在相同的后台线程和后台 MOC 上执行。读到这里:NSSortdescriptor ineffective on fetch result from NSManagedContext—“除非数据一直保存回持久存储,否则如果主上下文中的数据是脏的,即已修改,则排序将不起作用”,我尝试在步骤 3)中强制保存一直“向上” " 到持久存储(即磁盘)的嵌套 MOC 链,但这也没有效果:在 iOS 5.1 下(仅)此提取的结果未排序,除非我在执行提取后“手动”对结果进行排序.

4

2 回答 2

1

好的,经过进一步的实验,我确定确实,在 iOS 5.1 中(但不是在 iOS 6+ 中),如此处所述:NSSortdescriptor ineffective on fetch result from NSManagedContext —“除非数据一直保存回 Persistent Store ,如果主上下文中的数据是脏的,即已修改,则排序将不起作用。如果我在执行获取请求之前将所有实体更改(插入、修改、删除)保存到持久存储(执行同步保存一直到嵌套 MOC 链到磁盘 MOC),则结果会正确排序。如果我不这样做,则结果不会排序。

所以:如果您的应用程序需要在 iOS 5.1 下运行,并且如果您使用嵌套的 MOC,您必须 1)在执行排序获取请求之前一直“向上”保存到您的持久存储(例如磁盘),或 2)应用对获取的结果数组进行排序。

(即使这个问题实际上在链接的帖子中得到了回答,我还是会留下这个问题并在这里回答,直到/除非被要求删除它,因为我认为它更清楚更明确地说明了问题所在它的解决方案是。)

于 2013-09-27T15:09:20.707 回答
0
  1. 您可能不想以这种方式使用 performBlockAndWait。它仅用于可重入,因此它无法执行 performBlock 为您执行的某些操作 - 例如自动释放池和用户事件。用户事件对于核心数据按预期运行非常重要。例如,在 performBlockAndWait 中所做的更改不会触发 NSManagedObjectContext 通知!有关更多信息,请参阅iOS 5 Core Data 发行说明

  2. iOS 5.x 上的 CoreData 存在许多已知问题,这些问题在 iOS 6 上已修复。太多无法列出。如果父上下文发生变化,排序将不起作用,我确实认为还有另一个关于排序的问题。不幸的是,我不再有这些的雷达号码。

如 WWDC 2012 session 214 "Core Data Best Practices" 所示,如果您使用带有信号量的 performBlock 代替 performBlockAndWait,您是否会遇到相同的排序问题?

于 2013-09-27T01:07:28.213 回答