应用程序在Nsdata持久存储调用上崩溃

时间:2014-01-16 13:08:41

标签: objective-c cocoa-touch core-data nsfetchrequest

我有一个方法在应用从后台恢复活动时调用NSfetch request。有时由于NsnotificationManager,有两个实例正在调用此方法。

当我查看我的应用程序崩溃日志时,它显示了这个

2   CoreData                        0x30321a90 -[_PFLock lock] + 20
3   CoreData                        0x30332b34 -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 776
4   CoreData                        0x30331776 -[NSManagedObjectContext executeFetchRequest:error:] + 610
5   My app                      0x000ee7e0 -[ViewController CheckExistingData] (ViewController.m:350)

第350行的陈述是:

 NSArray *array = [[self managedObjectContext] executeFetchRequest:fetch error:&error];

这种情况偶尔发生,很少没有任何固定的步骤来重现。当我检查日志时,这通常发生在同时调用此方法2次时;一个由NSnotification经理和一个由View确实出现。我尝试将@syncronided()添加到被调用两次的方法但我面临同样的错误。有没有其他方法可以确保一个线程访问NSfetch /像添加一个锁或其他东西。

对此的任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

您可能违反了Core Data并发规则。

如果您的上下文属于旧线程限制类型,则需要确保始终从一个线程或串行队列访问它。

如果您的上下文是主队列并发类型,则需要确保从主队列或通过调用-performBlock...:方法之一来使用它。

如果您的上下文是私有队列并发类型,则必须使用-performBlock...:方法之一。

以下是一些例子。

线程限制

如果您创建这样的上下文:

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];

或者:

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];

您只能从一个线程或串行队列(创建它的位置)使用此上下文(以及从中获取的所有托管对象)。

专用队列并发

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

您只能使用特殊方法-performBlock:-performBlockAndWait:处理此上下文及其托管对象:

[context performBlock:^{
    // Assume error and request exist.
    NSArray *objects = [context executeFetchRequest:request error:&error];
}];

主队列并发类型

NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

与专用队列并发类型相同。但是因为使用了主队列,所以在主队列中,您可以直接使用上下文,而无需将调用包装到-performBlock...:方法中。