Core Data Freeze at fetch request ( Deadlock )

时间秒杀一切 提交于 2019-12-11 16:47:58

问题


i'm trying to realize fetch request, but it seems to be in deadlock.

> 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

I have that methods to make my child context:

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);
            }

        }

    }];
}

My fetch method:

+(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;

}

My child context is NSPrivateQueueConcurrencyType and all saves is done using performBlock.

What I suppose to do to make this run correctly?

Thank you.


回答1:


You mention that "all saves is done using performBlock", which is good but not enough. NSManagedObjectContext is not thread safe for pretty much everything. Your fetch request is not in the context of a performBlock, but it really needs to be. Also, everything else you use the context for, as well as when you use the managed objects that you fetch. Deadlocking like this is a classic symptom of threading issues, which performBlock was designed to help avoid.




回答2:


I found the problem, my NSFetchedResultsController was not using child context with performBlock.

Thank you Tom Harrington.



来源:https://stackoverflow.com/questions/19576280/core-data-freeze-at-fetch-request-deadlock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!