大佬教程收集整理的这篇文章主要介绍了ios – 具有多个线程的CoreData死锁,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
if (![moc save:&error])
…当发生死锁时,这似乎总是在后台线程的保存中.每次通话都不会发生;事实上它完全相反,我必须使用我的应用程序几分钟然后它会发生.
我已经阅读了我能找到的所有帖子以及Apple文档等,我确信我正在遵循这些建议.具体而言,我对使用多个MOC /线程的理解归结为:
>每个线程必须有自己的MOC.
>必须在该线程上创建线程的MOC(不从一个线程传递到另一个线程).
>无法传递NsmanagedObject,但NsmanagedObjectID可以,并且您使用该ID使用不同的MOC来扩充NsmanagedObject.
>如果@L_760_2@mOC的更改都使用相同的PersistentStoreCoordinator,则必须将其合并到另@L_760_2@mOC.
不久之前,我在this SO thread上遇到了MOC助手类的一些代码,发现它很容易理解并且使用起来非常方便,因此我所有的MOC交互都是通过它进行的.这是我的ManagedObjectContextHelper类的完整内容:
#import "ManagedObjectContextHelper.h" @implementation ManagedObjectContextHelper +(void)initialize { [[NsnotificationCenter defaultCenter] addObserver:[self class] SELEctor:@SELEctor(threadExit:) name:NSThreadWillExitNotification object:nil]; } +(void)threadExit:(Nsnotification *)aNotification { TDAppDelegate *delegate = (TDAppDelegate *)[[UIApplication sharedApplication] delegate]; NSString *threadKey = [NSString StringWithFormat:@"%p",[NSThread currentThread]]; NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts; [managedObjectContexts removeObjectForKey:threadKey]; } +(NsmanagedObjectContext *)managedObjectContext { TDAppDelegate *delegate = (TDAppDelegate *)[[UIApplication sharedApplication] delegate]; NsmanagedObjectContext *moc = delegate.managedObjectContext; NSThread *thread = [NSThread currentThread]; if ([thread ismainThread]) { [moc setMergePolicy:NSErrorMergePolicy]; return moc; } // a key to cache the context for the given thread NSString *threadKey = [NSString StringWithFormat:@"%p",thread]; // delegate.managedObjectContexts is a mutable Dictionary in the app delegate NSMutableDictionary *managedObjectContexts = delegate.managedObjectContexts; if ( [managedObjectContexts objectForKey:threadKey] == nil ) { // create a context for this thread NsmanagedObjectContext *thReadContext = [[NsmanagedObjectContext alloc] init]; [thReadContext setPersistentStoreCoordinator:[moc persistentStoreCoordinator]]; [thReadContext setMergePolicy:NSErrorMergePolicy]; // cache the context for this thread NSLog(@"Adding a new thread:%@",threadKey); [managedObjectContexts setObject:thReadContext forKey:threadKey]; } return [managedObjectContexts objectForKey:threadKey]; } +(void)commit { // get the moc for this thread NsmanagedObjectContext *moc = [self managedObjectContext]; NSThread *thread = [NSThread currentThread]; if ([thread ismainThread] == NO) { // only observe notifications other than the main thread [[NsnotificationCenter defaultCenter] addObserver:[self class] SELEctor:@SELEctor(contextDidSave:) name:NsmanagedObjectContextDidSaveNotification object:moc]; } NSError *error; if (![moc save:&error]) { NSLog(@"Failure is happening on %@ thread",[thread ismainThread]?@"main":@"other"); NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey]; if(detailedErrors != nil && [detailedErrors count] > 0) { for(NSError* detailedError in detailedErrors) { NSLog(@" DetailedError: %@",[detailedError userInfo]); } } NSLog(@" %@",[error userInfo]); } if ([thread ismainThread] == NO) { [[NsnotificationCenter defaultCenter] removeObserver:[self class] name:NsmanagedObjectContextDidSaveNotification object:moc]; } } +(void)contextDidSave:(Nsnotification*)saveNotification { TDAppDelegate *delegate = (TDAppDelegate *)[[UIApplication sharedApplication] delegate]; NsmanagedObjectContext *moc = delegate.managedObjectContext; [moc performSELEctorOnMainThread:@SELEctor(mergeChangesFromContextDidSaveNotification:) withObject:saveNotification waitUntilDone:NO]; } @end
这是多线程位的片段,它似乎在死锁:
NsmanagedObjectID *parentObjectID = [parent objectID]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0ul); dispatch_async(queue,^{ // GET BACKGROUND MOC NsmanagedObjectContext *BACkgroundContext = [ManagedObjectContextHelper managedObjectContext]; Parent *BACkgroundParent = (Parent*)[BACkgroundContext objectWithID:parentObjectID]; // HIT THE WEBserviCE AND PUT THE RESULTS IN THE PARENT OBjeCT AND ITS CHILDREN,THEN SAVE... [ManagedObjectContextHelper commit]; dispatch_sync(dispatch_get_main_queue(),^{ NsmanagedObjectContext *mainManagedObjectContext = [ManagedObjectContextHelper managedObjectContext]; parent = (Parent*)[mainManagedObjectContext objectWithID:parentObjectID]; }); });
错误中的conflictList似乎暗示它与父对象的ObjectID有关:
conflictList = ( "NSMergeConflict (0x856b130) for NsmanagedObject (0x93a60e0) with objectID '0xb07a6c0 <x-coredata://B7371EA1-2532-4D2B-8F3A-E09B56CC04F3/Child/p4>' with oldVersion = 21 and newVersion = 22 and old object snapshot = {\n parent = \"0xb192280 <x-coredata://B7371EA1-2532-4D2B-8F3A-E09B56CC04F3/Parent/p3>\";\n name = \"New Child\";\n returnedChildId = 337046373;\n time = 38;\n} and new cached row = {\n parent = \"0x856b000 <x-coredata://B7371EA1-2532-4D2B-8F3A-E09B56CC04F3/Parent/p3>\";\n name = \"New Child\";\n returnedChildId = 337046373;\n time = 38;\n}" );
一旦我掌握了MOC,我就尝试放入refreshObject调用,理论上如果这是我们之前使用过的MOC(例如我们之前在主线程上使用了MOC而且很可能是这与助手类给我们的一样,然后在另一个线程中保存可能意味着我们需要显式刷新.但它没有任何区别,如果我长时间点击,它仍然会陷入僵局.
有没有人有任何想法?
编辑:如果我为所有例外设置了断点,则调试器会自动暂停if(![moc save:& error])行,因此播放/暂停按钮已暂停并显示播放三角形.如果我禁用所有异常的断点,那么它实际记录冲突并继续 – 可能是因为合并策略当前设置为NSErrorMergePolicy – 所以我不认为它实际上是在线程上死锁.暂停时两个线程状态的@L_801_17@.
另请注意,dispatch_get_global_queue提供并发队列,不能用于同步.
编辑
您正在尝试手动管理MOC和线程.如果你愿意,你可以做到,但你的道路上有龙.这就是创建新方法的原因,以最大限度地减少跨多个线程使用COre Data时出错的可能性.每当我看到使用COre Data进行手动线程管理时,我总是建议改变第一种方法.这将立即消除大多数错误.
我不需要看到比手动映射MOC和线程更多的东西,知道你在寻找麻烦.只需重新阅读该文档,并以正确的方式执行(使用PerformBlock).
以上是大佬教程为你收集整理的ios – 具有多个线程的CoreData死锁全部内容,希望文章能够帮你解决ios – 具有多个线程的CoreData死锁所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。