我有一个获取请求“foo”,我有一个排序描述符(它按降序排序Integer 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];
然后正确排序结果。
还有其他人遇到过这样的事吗?如果是的话,你找到了原因吗?
谢谢!
卡尔
P.S。:如果证明相关,这里是“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 - “除非数据一直保存回Persistent Store,否则如果主上下文中的数据是脏的,即修改后,排序将不起作用”,我试图强制保存在步骤3))所有方式“嵌套”嵌套的MOC链到持久存储(即,到磁盘),但这也没有影响:在iOS 5.1(仅)下,此提取的结果未排序,除非我排序执行提取后“手动”结果。
答案 0 :(得分:1)
好的,经过进一步的实验,我确定,确实,iOS 5.1中的 (但不是iOS 6+),如下所述:NSSortdescriptor ineffective on fetch result from NSManagedContext - “除非数据是一直保存回持久存储,如果主上下文中的数据是脏的,即修改后,排序将不起作用。如果我在执行获取请求之前将所有实体更改(插入,修改,删除)保存到持久性存储(在嵌套MOC链中一直执行同步保存到磁盘-MOC),则会对结果进行正确排序。如果我不这样做,结果不会排序。
所以:如果您的应用程序需要在iOS 5.1下运行,并且您使用嵌套的MOC,则必须1)在执行已排序的提取请求之前将所有方式“向上”保存到持久性存储(例如磁盘),或者2)自己对取得的结果数组进行排序。
(即使这个问题实际上已经在链接的帖子中得到解答,我将留下这个问题并在这里回答,直到/除非要求删除它,因为我认为它更清楚,更明确问题及其解决方案是什么。)
答案 1 :(得分:0)
您可能不希望以这种方式使用performBlockAndWait。它仅用于重入,因此它无法执行performBlock为您所做的一些事情 - 如自动释放池和用户事件。用户事件对于核心数据按预期运行非常重要。例如,在performBlockAndWait内进行的更改不会触发NSManagedObjectContext通知!有关详细信息,请参阅iOS 5 Core Data release notes。
iOS 5.x上的CoreData存在许多已知问题,这些问题已在iOS 6上修复。要列出的内容太多。如果父上下文中有更改,那么排序将无法正常工作,我确实认为还有另一个关于排序的问题。不幸的是,我不再拥有雷达数字。
如果使用带有信号量的performBlock代替performBlockAndWait,您是否会遇到相同的排序问题,如WWDC 2012会话214“核心数据最佳实践”中所示?