Core Data Freeze at fetch request(死锁)
Posted
技术标签:
【中文标题】Core Data Freeze at fetch request(死锁)【英文标题】:Core Data Freeze at fetch request ( Deadlock ) 【发布时间】:2013-10-24 20:44:53 【问题描述】:我正在尝试实现获取请求,但它似乎陷入了僵局。
> Thread 1, Queue : com.apple.main-thread
> #0 0x38329fa8 in __psynch_mutexwait ()
> #1 0x38390f0e in _pthread_mutex_lock ()
> #2 0x2d3aaad0 in -[_PFLock lock] ()
> #3 0x2d3bbba4 in -[NSPersistentStoreCoordinator executeRequest:withContext:error:] ()
> #4 0x2d3ba7e6 in -[NSManagedObjectContext executeFetchRequest:error:] ()
> #5 0x2d448bb6 in -[NSManagedObjectContext(_NestedContextSupport) _parentObjectsForFetchRequest:inContext:error:] ()
> #6 0x2d44932e in __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke ()
> #7 0x2d43ec82 in _perform ()
> #8 0x2d449030 in -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:] ()
> #9 0x2d3ba7e6 in -[NSManagedObjectContext executeFetchRequest:error:] ()
> #10 0x000e4c90 in +[PhotoDAO getNotSentPhotos:] at /Users/vitrinysolutions/Documents/Workspace XCode/Novo
> SmileClick/SmileClick/SmileClick/DAOs/PhotoDAO.m:236
> #11 0x0009f210 in -[EventManager loadQueue:] at /Users/vitrinysolutions/Documents/Workspace XCode/Novo
> SmileClick/SmileClick/SmileClick/Util/EventManager.m:59
> #12 0x00095fb0 in -[EventMainViewController viewDidAppear:] at /Users/vitrinysolutions/Documents/Workspace XCode/Novo
> SmileClick/SmileClick/SmileClick/ViewControllers/EventMainViewController.m:60
> #13 0x2fdf03da in -[UIViewController _setViewAppearState:isAnimating:] ()
> #14 0x2fdf085c in -[UIViewController _endAppearanceTransition:] ()
> #15 0x2fe9ced2 in -[UINavigationController navigationTransitionView:didEndTransition:fromView:toView:] ()
> #16 0x2ff6831c in __49-[UINavigationController _startCustomTransition:]_block_invoke ()
> #17 0x2feecc22 in -[_UIViewControllerTransitionContext completeTransition:] ()
> #18 0x2ffacff6 in __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke105 ()
> #19 0x2fe0dfe8 in -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] ()
> #20 0x2fe0dc36 in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] ()
> #21 0x2fe0db4e in -[UIViewAnimationState animationDidStop:finished:] ()
> #22 0x2fa65d08 in CA::Layer::run_animation_callbacks(void*) ()
> #23 0x3824ed66 in _dispatch_client_callout ()
> #24 0x382557c0 in _dispatch_main_queue_callback_4CF$VARIANT$mp ()
> #25 0x2d62f820 in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
> #26 0x2d62e0f4 in __CFRunLoopRun ()
> #27 0x2d598ce6 in CFRunLoopRunSpecific ()
> #28 0x2d598aca in CFRunLoopRunInMode ()
> #29 0x32286282 in GSEventRunModal ()
> #30 0x2fe3aa40 in UIApplicationMain ()
> #31 0x000aeedc in main at /Users/vitrinysolutions/Documents/Workspace XCode/Novo SmileClick/SmileClick/SmileClick/main.m:16
我有这些方法可以让我的孩子上下文:
static __strong NSManagedObjectContext *context;
+(NSManagedObjectContext*) context
if (context == nil)
context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext: [((AppDelegate*)[[UIApplication sharedApplication] delegate]) managedObjectContext]];
return context;
+ (void)save:(NSManagedObjectContext *)context
[context performBlockAndWait:^
NSError *error;
if (![context save:&error])
NSLog(@"Child Context Error: %@", error);
else
NSManagedObjectContext *parentContext = [((AppDelegate*)[[UIApplication sharedApplication] delegate]) managedObjectContext];
if (![parentContext save:&error])
NSLog(@"Parent Context Error: %@", error);
];
我的获取方法:
+(NSArray *) getNotSentPhotos: (Event *) oEvent
NSManagedObjectContext *context = [self context];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Photo" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(event == %@) AND (server_status == %@)", oEvent, SERVER_STATUS_PENDENTE];
[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
return fetchedObjects;
我的子上下文是 NSPrivateQueueConcurrencyType,所有保存都是使用 performBlock
完成的。
我应该怎么做才能使它正确运行?
谢谢。
【问题讨论】:
【参考方案1】:您提到“所有保存都是使用performBlock
”完成的,这很好但还不够。 NSManagedObjectContext
对几乎所有东西都不是线程安全的。您的 fetch 请求不在 performBlock
的上下文中,但确实需要。此外,您使用上下文的所有其他内容,以及您使用获取的托管对象的时间。像这样的死锁是线程问题的典型症状,performBlock
旨在帮助避免这种情况。
【讨论】:
谢谢,但我为此更新了我的代码:link,但仍处于死锁状态。代码下面有堆栈。 这是获取您使用上下文的唯一位置,还是您获取的任何对象?这似乎不太可能,因为您返回一个对象数组而不查看它们。仅将 fetch 放入 performBlock 是不够的。可能涉及上下文的所有内容都需要同步。 我发现了问题,我的 NSFetchedResultsController 没有使用带有 performBlock 的子上下文。谢谢汤姆哈灵顿。以上是关于Core Data Freeze at fetch request(死锁)的主要内容,如果未能解决你的问题,请参考以下文章
iOS Core Data Fetch Request,如何使用
Core Data Fetch 在插入实体时保存关系(同时)
如何确保从上下文而不是缓存中获取 Core Data Fetched Property?