0

我的问题是这样的。我想异步保存到磁盘。设置核心数据堆栈的代码如下所示。

- (NSManagedObjectContext *)managedObjectContext {
NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    NSManagedObjectContext *privateMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [privateMOC setPersistentStoreCoordinator:coordinator];
    __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [__managedObjectContext setParentContext:privateMOC];


});
return __managedObjectContext;
}

当我执行这样的提取时:

NSMutableArray *result = [NSMutableArray array];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:[DataObject entityName]
                                          inManagedObjectContext:self.managedObjectContext];

[request setEntity:entity];
[request setPredicate:[NSPredicate predicateWithFormat:@"SUBQUERY(threadEntities, $emp, $emp.thread = %@).@count>0 AND tags.@count!=0", self, nil ]];
[request setPropertiesToFetch:@[@"creationDate", @"data"]];
[request setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]]];
NSError *error = nil;

[result addObjectsFromArray:[self.managedObjectContext executeFetchRequest:request error:&error]];

它因此错误而崩溃:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 375961053 beyond bounds [0 .. 7]'

另一方面,像这样的堆栈设置效果很好:

  - (NSManagedObjectContext *)managedObjectContext {
NSPersistentStoreCoordinator *coordinator = self.persistentStoreCoordinator;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [__managedObjectContext setPersistentStoreCoordinator:coordinator];
});
return __managedObjectContext;
}

数据库内部有一个 DataObject 和一些用于管理它的附加对象。问题是,为什么这个 fetch 会受到影响,而应用程序之前使用相同参数执行的计数两次都有效?

4

1 回答 1

0

看起来 CoreData 内部的某些东西变得不一致,好像您也在处理错误的合并通知(使用父子时您不应该这样做,也不应该尝试!)。不幸的是,如果没有完整的堆栈跟踪,就很难重建这里发生的事情。

但是,我认为没有理由在 dispatch_once 块内设置主队列上下文。上下文很便宜,没有理由每次你需要一个新的子上下文时不生成一个新的子上下文 - 这是使用它们的推荐方式。NSManagedObjectContext是:

NSManagedObjectContext 的一个实例代表应用程序中的单个“对象空间”或便笺簿。它的主要职责是管理托管对象的集合。这些对象形成一组相关的模型对象,代表一个或多个持久存储的内部一致视图。

并与父子

当您在上下文中保存更改时,更改只会“一次存储”提交。如果您保存子上下文,则会将更改推送到其父上下文。在保存根上下文之前,这些更改不会保存到持久存储中。(根托管对象上下文是其父对象为 nil 的上下文。)此外,父对象在保存之前不会从子对象中提取更改。如果要最终提交更改,则必须保存子上下文。

嵌套上下文比以往任何时候都更重要的是,采用“传递接力棒”的方法来访问上下文(通过将上下文从一个视图控制器传递到下一个视图控制器)而不是直接从应用程序委托中检索它。

如果您想查看设置父子上下文和使用队列限制的简单示例: https ://github.com/quellish/QueuedCoreData

于 2013-10-14T02:02:42.910 回答