CoreData崩溃,主队列上下文设置为私有队列上下文的子级

时间:2012-11-30 13:58:58

标签: objective-c ios core-data concurrency

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

- (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,还有一些用于管理它的附加对象。问题是,为什么这个提取会受到影响,而app之前用相同参数执行的计数会同时工作?

1 个答案:

答案 0 :(得分:0)

看起来CoreData内部的东西变得不一致,好像你也处理了一个错误的合并通知(使用父子时你不应该这样做,而且不应该尝试!)。遗憾的是,没有完整的堆栈跟踪,重建这里发生的事情将非常困难。

但是我没有看到 reason 在dispatch_once块中设置主队列上下文。上下文变得便宜,没有理由不在每次需要时生成新的子上下文 - 这是使用它们的推荐方法。 NSManagedObjectContext是:

  

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

使用parent-child

  

在上下文中保存更改时,仅提交更改   “一个存储起来。”如果您保存子上下文,则会将更改推送到其中   家长。直到这些更改才会保存到持久性存储中   根上下文已保存。 (根管理对象上下文是其中的一个   parent是nil。)此外,父母不会从中提取更改   孩子们节省之前。如果需要,您必须保存子上下文   最终要做出改变。

     

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

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