我有一个方法在应用从后台恢复活动时调用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
/像添加一个锁或其他东西。
对此的任何帮助将不胜感激。
答案 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...:
方法中。