Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crash with -com.apple.CoreData.ConcurrencyDebug 1 when fetching entites #950

Closed
JanC opened this issue Jan 31, 2015 · 5 comments
Closed

Comments

@JanC
Copy link

JanC commented Jan 31, 2015

Hi,
every time I fetch and access a NSManagedObject in a background thread with -com.apple.CoreData.ConcurrencyDebug 1, I get a crash. It is reproducible with:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    PSPlayer *player = [[PSPlayer MR_findAll] firstObject];
    NSLog(@"player = %@", player.name);
});

I'm using 2.3.0 beta 5

@Alydyn
Copy link

Alydyn commented Jan 31, 2015

Thats because you are fetching in background without specifying a context. -MR_findAll uses MR_contextForCurrentThread which is no longer recommended.
Try this:

NSManagedObjectContext *context = [NSManagedObjectContext MR_context];
[context performBlock:^{
    PSPlayer *player = [[PSPlayer MR_findAllInContext:context] firstObject];
    NSLog(@"player = %@", player.name);
}];

@JanC
Copy link
Author

JanC commented Jan 31, 2015

ok, I see. I thought that all the methods described in the docs were guaranteeing to use the appropriate context. Also, I have to surround the access with [context performBlock:^{ ... so the docs are not yet updated for 2.3, correct?

@JanC JanC closed this as completed Feb 1, 2015
@JanC JanC reopened this Feb 1, 2015
@JanC
Copy link
Author

JanC commented Feb 1, 2015

Now, how come I have the crash when calling this in a main method of a NSOperation ?

- (void)main
{
    @autoreleasepool {
        NSManagedObjectContext *context = [NSManagedObjectContext MR_context];
        PSPlayer *player = (PSPlayer *) [context objectWithID:self.playerId];
        NSLog(@"name = %@", player.name);
        // rest  of NSOperation logic
    }
}

Do I have to wrap the entire logic of the NSOperation in performBlockAndWait

- (void)main
{
    @autoreleasepool {

        __block BOOL keepUpdating = YES;

        __block PSPlayer *player;
        NSManagedObjectContext *context = [NSManagedObjectContext MR_context];
        [context performBlockAndWait:^{
            player = (PSPlayer *) [context objectWithID:self.playerId];
            NSLog(@"name = %@", player.name);
            // rest  of NSOperation logic
        }];
    }
}

@Alydyn
Copy link

Alydyn commented Feb 1, 2015

NSOperation's -main method will almost certainly be called on a different thread than -start for concurrent operations. First, try creating the context in -start. And then, yes, you will need to wrap access in -performBlockAndWait:
An excellent write up is on objc.io

@JanC
Copy link
Author

JanC commented Feb 1, 2015

ok thanks. objc.io is my Bible but it looks like I should read it more often. cheers

@JanC JanC closed this as completed Feb 1, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants