save:
子类上的Managedobjectcontext NSOperation
查询会导致此异常。我不确定这里出了什么问题,但似乎是一个线程锁定问题。任何人都可以帮我解决这个问题吗?
多个NSOperation
子类正在使用一个PSC,每个子类都有自己的MOC。也许我需要将@synchronized
放在某处以保证线程安全?
Fatal Exception: NSInternalInconsistencyException
This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operation.
Thread : Fatal Exception: NSInternalInconsistencyException
0 CoreFoundation 0x3018af0b __exceptionPreprocess + 130
1 libobjc.A.dylib 0x3a921ce7 objc_exception_throw + 38
2 CoreData 0x2fedd689 -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 3228
3 CoreData 0x2fefef49 -[NSManagedObjectContext save:] + 824
4 ChevronRetail 0x0006aae5 -[MyParseOperation myMethod:] (MyParseOperation.m:159)
5 ChevronRetail 0x0006adbf -[MyParseOperation main] (StationFinderParseOperation.m:192)
6 Foundation 0x30abe875 -[__NSOperationInternal _start:] + 772
7 Foundation 0x30b62745 __NSOQSchedule_f + 60
其他信息: PersistentStoreCoordinator保存在由多个控制器中的MOC访问的appdelegate中
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSString *documentsDirectoryPath = [self applicationDocumentsDirectory];
NSString *storePath = [documentsDirectoryPath stringByAppendingPathComponent:@"MyDatabase.sqlite"];
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
//abort();
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [NSManagedObjectContext new];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
[_managedObjectContext setMergePolicy:NSOverwriteMergePolicy];
return _managedObjectContext;
}
答案 0 :(得分:0)
Apple样板PSC初始化代码不是线程安全的(MOC初始化代码也不是。) HERE您可以找到类似的问题。
在多线程环境中,2个(或更多)线程可以调用PSC初始化代码 解决方法是在“应用程序完成启动...”中添加这些行:
[self persistentStoreCoordinator];
[self managedObjectContext];
BEFORE 发布使用CoreData堆栈的 ANY 操作/流程。
这确保只有一个线程(主线程)正在初始化堆栈,但是这否定了当前实现试图实现的“延迟加载”原则。
错误的原因是这种执行流程:
线程1测试是否有_persistentStoreCoordinator
并且发现它为零。
线程2测试是否有_persistentStoreCoordinator
并且发现它为零
线程1和线程2继续进入初始化代码部分
线程1到达线(但尚未返回):
return _persistentStoreCoordinator;
线程2执行以下行:
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
线程1返回没有存储的协调器,并在操作中使用它来初始化私有MOC,MOC保存并崩溃。
为了让“延迟加载”梦想保持活力,你可以用这种方式实现初始化代码:
//UNTESTED
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {//someone already initilized this part of the stack
return _persistentStoreCoordinator;//no need to lock
}
@synchronized(self) {
if (_persistentStoreCoordinator == nil) {//check under lock
_persistentStoreCoordinator = [self __persistentStoreCoordinator];//only one thread could set the ivar
}
}
return _persistentStoreCoordinator;
}
- (NSPersistentStoreCoordinator*) __persistentStoreCoordinator
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyDatabase.sqlite"];
NSError *error = nil;
NSPersistentStoreCoordinator* coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return coordinator;//always return a full fledged coordinator
}
你可以使用你喜欢的任何同步机制来防止这种竞争条件,这只是一个简单的例子。
此竞争条件也适用于managedObjectModel
和managedObjectContext
解决方案类似。