我目前正尝试实施方案:
MOC1(PrivateQueue)-parent-> MOC2(MainQueue)-parent-> MOC3(PrivateQueue),PSC保存
这是init代码(MOC2& MOC#:
_writeManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_writeManagedObjectContext.persistentStoreCoordinator = coordinator;
_writeManagedObjectContext.undoManager = nil;
_mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_mainManagedObjectContext.undoManager = nil;
_mainManagedObjectContext.parentContext = _writeManagedObjectContext;
这是init MOC1:
_mocSSchild = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_mocSSchild.undoManager = nil;
_mocSSchild.parentContext = delegateMain.mainManagedObjectContext;
这是一个保存:
NSError *error = nil;
[self.mocSSchild obtainPermanentIDsForObjects:self.mocSSchild.insertedObjects.allObjects error:&error];
if (![self.mocSSchild save: &error]) {
NSLog(@"Failed to save to FIRST data store: %@", [error localizedDescription]);
NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors != nil && [detailedErrors count] > 0)
{
for(NSError* detailedError in detailedErrors)
{
NSLog(@" DetailedError: %@", [detailedError userInfo]);
}
}
else
{
NSLog(@" %@", [error userInfo]);
}
}
AppDelegate *delegateMain = (AppDelegate *)[[NSApplication sharedApplication] delegate];
if ([delegateMain.mainManagedObjectContext hasChanges] && ![delegateMain.mainManagedObjectContext save: &error]) { NSLog(@"Failed to save to FIRST data store: %@", [error localizedDescription]);
NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors != nil && [detailedErrors count] > 0)
{
for(NSError* detailedError in detailedErrors)
{
NSLog(@" DetailedError: %@", [detailedError userInfo]);
}
}
else
{
NSLog(@" %@", [error userInfo]);
}
}
if ([delegateMain.writeManagedObjectContext hasChanges] && ![delegateMain.writeManagedObjectContext save: &error]) { NSLog(@"Failed to save to FIRST data store: %@", [error localizedDescription]);
NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
if(detailedErrors != nil && [detailedErrors count] > 0)
{
for(NSError* detailedError in detailedErrors)
{
NSLog(@" DetailedError: %@", [detailedError userInfo]);
}
}
else
{
NSLog(@" %@", [error userInfo]);
}
}
所有获取请求都放在右侧块中(当然我从不接触mainManagedObjectContext来执行获取请求):
__block NSError *error = nil;
__block NSArray *findedResult = nil;
[self.mocSSchild performBlockAndWait:^{
findedResult = [self.mocSSchild executeFetchRequest:fetchRequest error:&error];
}];
一次保存后,我在主队列中冻结(看起来像核心数据尝试在mainManagedObjectContext上执行获取请求,我不做请求):
Call graph:
2633 Thread_803320 DispatchQueue_173: NSManagedObjectContext Queue (serial)
+ 2633 start (in libdyld.dylib) + 1 [0x7fff8bb907e1]
+ 2633 main (in callsfreecall) + 34 [0x10992c202]
+ 2633 NSApplicationMain (in AppKit) + 869 [0x7fff8a49cbd6]
+ 2633 -[NSApplication run] (in AppKit) + 517 [0x7fff8a4f81a3]
+ 2633 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] (in AppKit) + 128 [0x7fff8a500df2]
+ 2633 _DPSNextEvent (in AppKit) + 685 [0x7fff8a501533]
+ 2633 BlockUntilNextEventMatchingListInMode (in HIToolbox) + 62 [0x7fff8f356ae3]
+ 2633 ReceiveNextEventCommon (in HIToolbox) + 356 [0x7fff8f356c52]
+ 2633 RunCurrentEventLoopInMode (in HIToolbox) + 209 [0x7fff8f356eb4]
+ 2633 CFRunLoopRunSpecific (in CoreFoundation) + 290 [0x7fff9526c0e2]
+ 2633 __CFRunLoopRun (in CoreFoundation) + 1644 [0x7fff9526cb4c]
+ 2633 _dispatch_main_queue_callback_4CF (in libdispatch.dylib) + 275 [0x7fff8c4c20c8]
+ 2633 _dispatch_client_callout (in libdispatch.dylib) + 8 [0x7fff8c4bd0b6]
+ 2633 _dispatch_barrier_sync_f_slow_invoke (in libdispatch.dylib) + 77 [0x7fff8c4c2a2d]
+ 2633 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke_0 (in CoreData) + 533 [0x7fff93d8b6c5]
+ 2633 -[NSManagedObjectContext countForFetchRequest:error:] (in CoreData) + 1563 [0x7fff93d65ddb]
+ 2633 -[NSManagedObjectContext(_NSInternalAdditions) _countWithNoChangesForRequest:error:] (in CoreData) + 298 [0x7fff93d65f4a]
+ 2633 -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] (in CoreData) + 354 [0x7fff93d576c2]
+ 2633 _perform (in CoreData) + 172 [0x7fff93d5787c]
+ 2633 _dispatch_barrier_sync_f_invoke (in libdispatch.dylib) + 39 [0x7fff8c4be723]
+ 2633 _dispatch_client_callout (in libdispatch.dylib) + 8 [0x7fff8c4bd0b6]
+ 2633 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke_0 (in CoreData) + 533 [0x7fff93d8b6c5]
+ 2633 -[NSManagedObjectContext countForFetchRequest:error:] (in CoreData) + 1563 [0x7fff93d65ddb]
+ 2633 -[NSManagedObjectContext(_NSInternalAdditions) _countWithNoChangesForRequest:error:] (in CoreData) + 298 [0x7fff93d65f4a]
+ 2633 -[NSPersistentStoreCoordinator executeRequest:withContext:error:] (in CoreData) + 1138 [0x7fff93d10ba2]
+ 2633 -[_PFLock lock] (in CoreData) + 24 [0x7fff93cfe548]
+ 2633 pthread_mutex_lock (in libsystem_c.dylib) + 536 [0x7fff92797dfd]
+ 2633 __psynch_mutexwait (in libsystem_kernel.dylib) + 10 [0x7fff938ca122]
答案 0 :(得分:1)
首先,当您收到错误时,您需要做一些错误。现在你没有做任何事情,没有记录它们,没有对它们作出反应,没有任何反应。这是不好的。发生错误时,您根本没有任何迹象。你只需要进入下一步。
其次,您将所有MOC保存在同一队列中。任何针对私人MOC的活动都必须通过-performBlock:
或-performBlockAndWait:
方法在区块内执行。
第三,没有迹象表明你正在运行什么队列。
您的导入MOC应该在一个操作或运行异步的块中运行。导入MOC应该使用线程限制而不是私有MOC。一旦导入MOC完成其工作,它应该保存自己,然后向主队列指示应该保存主MOC。
主MOC应该只保存在主队列中。当主MOC完成其保存后,它应通过其-performBlock:
启动到顶级MOC的保存。
使用错误结果纠正您的问题,并查看您正在进行的工作队列。如果所有内容都在主队列中,则父/子MOC不会解决您的问题。你需要重新考虑在哪里开展的工作。
首先,您可以通过收听来自呼叫的结果来检测错误。如果调用返回BOOL
,则表示通过/失败。如果调用返回其他内容,那么如果其他内容为nil
,则表示失败并且错误将出现。
至于你的代码,不是不正确。你提到的话,你有线程问题。您正在直接触摸私人MOC,这是不正确的。可能还有其他错误,但根据此代码我无法看到它们。
您的“写作”MOC只能通过-performBlock:
或-performBlockAndWait:
来触及。在这种情况下,您应该使用-performBlock:
。你是直接触摸它。那很糟糕。
您的主要MOC只能在主要队列或-performBlock:
/ -performBlockAndWait:
上触及。您似乎直接在此代码中触摸它。
您正以单身人士的身份访问appDelegate
。这是一个糟糕的代码味道。查找并开始使用依赖注入。
当你的子moc应该是一个线程受限的上下文时,你的子moc被设置为私有,然后它只能在创建它的线程上访问,理想情况下应该在NSOperation中。
简而言之,您在这里缺少许多核心概念。您需要了解父/子上下文如何工作,并且在尝试开发这样的代码之前,您需要更好地理解队列和线程。