当我打开Concurrency调试开关时,com.apple.CoreData.ConcurrencyDebug 1'为了跟踪CoreData的所有并发问题,我在调用insertedNewObjectForEntityForName时不断遇到崩溃。
Xcode显示的消息是EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)。这是我的代码
这是我对managedObjectContext的实现
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
这里是[self privateContext]
的实现-(NSManagedObjectContext *)privateContext
{
NSManagedObjectContext *pvtContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
pvtContext.parentContext = [CoreDataMgr sharedInstance].managedObjectContext;
return pvtContext;
}
场景1:在主线程上执行 - 不会崩溃
NSManagedObjectContext *mainContext = [CoreDataMgr sharedInstance].managedObjectContext;
CDPayments* cdPayment = [NSEntityDescription insertNewObjectForEntityForName:PAYMENTS_TABLE inManagedObjectContext:mainContext];
场景2:在后台线程上执行 - CRASHES !!
NSManagedObjectContext *pvtContext = [self privateContext];
CDPayments* cdPayment = [NSEntityDescription insertNewObjectForEntityForName:PAYMENTS_TABLE pvtContext];
我真的不清楚为什么在私有上下文的后台线程上执行此操作会崩溃......
我正在使用Xcode 8对抗iOS9 SDK,并在保存付款对象时调用上述代码。
答案 0 :(得分:3)
这是因为您在核心数据并发性方面做错了。当您使用NSPrivateQueueConcurrencyType
或NSMainQueueConcurrencyType
时,必须将您的核心数据代码打包到perform()
或performAndWait()
。如果你不这样做,你的代码就违反了并发规则,完全可以预料到这种崩溃。
唯一的例外是如果你使用NSMainQueueConcurrencyType
并且某些代码在主队列上运行,你可以直接进行核心数据调用,而不必包装它们在街区。