1

My situation is that my app uses core data, and needs to load images from that core data to show in a table view. Because of the time it takes to do that, it needs to run in a background thread. So i have code such as this:

dispatch_async(queue, ^{

    if (self.cellInfo.numberOfMediaItems > 0) {

        int i = 0;

        int numberOfThumbnails = MIN(self.cellInfo.numberOfMediaItems, 3);

        while (i < numberOfThumbnails) {
            Media *media = [self.entry.media objectAtIndex:i];

            UIImage *image = [media getThumbnail];
            [self.mediaArray addObject:image];
            i++;
        }
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        self.isFinishedProcessing = YES;

        [self setNeedsDisplay];
    });

});

This speeds the process up considerably, and the images appear in the background when it's ready.

The problem is, sometimes it'll have the foreground thread try and access core data at the same time as the background thread. It doesn't like this, and so it crashes. This must be a situation that a lot of developers get in, and thus one with a solution. I wanted to know how to deal with the situation so my app stops crashing when they both start accessing core data at the same time?

Paul R
  • 208,748
  • 37
  • 389
  • 560
Andrew
  • 15,935
  • 28
  • 121
  • 203

2 Answers2

6

See my previous answer here.

There is a golden rule when it comes to Core Data - one Managed Object Context per thread. Managed object contexts are not thread safe so if you are doing work in a background task you either use the main thread to avoid threading conflicts with UI operations, or you create a new context to do the work in. If the work is going to take a few seconds then you should do the latter to stop your UI from locking up.

In short, you need to create a separate managed object context for use in your background thread. Then you have to merge changes back to the original context where appropriate.

Community
  • 1
  • 1
Mike Weller
  • 45,401
  • 15
  • 131
  • 151
1

You need to read Apple's Core Data programming guide.

Basically, NSManagedObjects and NSManagedObjectContexts are not thread safe. You will need to create a new NSManagedObjectContext on your background context to do the work. You cannot pass NSManagedObjects across threads. Instead you can store an array of NSManagedObjectIDs, and use that to "reload" the objects from the new context.

lorean
  • 2,150
  • 19
  • 25