当我打开并发调试开关'com.apple.CoreData.ConcurrencyDebug 1'来跟踪CoreData的所有并发问题时,我在调用insertingNewObjectForEntityForName时不断崩溃。
消息Xcode显示我是EXC_BAD_INSTRUCTION (code=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:执行后台线程-崩溃!!
NSManagedObjectContext *pvtContext = [self privateContext];
CDPayments* cdPayment = [NSEntityDescription insertNewObjectForEntityForName:PAYMENTS_TABLE pvtContext];
我真的不清楚为什么在一个私有上下文的后台线程上执行这个会崩溃…
我使用Xcode 8对iOS9 SDK和上述代码被调用时保存支付对象
这是因为你做Core Data并发错误。当您使用NSPrivateQueueConcurrencyType
或NSMainQueueConcurrencyType
时,必须将核心数据代码封装在perform()
或performAndWait()
的调用中。如果你不这样做,你的代码违反了并发规则,这个崩溃是完全可以预料的。
唯一的例外是,如果你使用NSMainQueueConcurrencyType
,你是某些,代码是运行在主队列上,你可以使核心数据调用直接,而不是包装它们在块。