Nikolay Dyankov
Nikolay Dyankov

Reputation: 7224

How to use Core Data in it's own thread?

I'm making an app very similar to the 9gag app and I'm struggling to get smooth scrolling, so I'm trying to get everything off the main thread. The thing that gives me trouble is Core Data.

I have a class PhotoSource, which creates it's own thread like this:

@property (nonatomic) dispatch_queue_t photoSourceThread;
...
dispatch_async(self.photoSourceThread, ^{ ... });

And I have another class, which deals only with Core Data:

@property (nonatomic, strong) TLCoreDataManager *coreDataManager;

Everything in the PhotoSource class happens inside it's thread, including the calls to TLCoreDataManager, like this:

dispatch_async(self.photoSourceThread, ^{
Photo *storedPhoto = [self.coreDataManager getPhotoWithURLString:urlString];
...
});

Sometimes it works, but right after app launch I get 0 results from my NSFetchRequest[s] and I don't know what to do. Any ideas what might be wrong? Please let me know if you need more code!

Thanks

Upvotes: 0

Views: 105

Answers (1)

Dan Shelly
Dan Shelly

Reputation: 6011

To use CoreData in a multithreaded environment for mutating your data and to eventually update you GUI will require you to merge changes to a main queue based context (the default context in the default code generated by a core data based application). I recommend you use a fetch results controller for listening to changes done to you data.

you can use something like:

/*!
 @see http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html
 */
- (void) doSomethingInBackgroundWithoutBlocking:(NSPersistentStoreCoordinator*)coordinator
{
    NSManagedObjectContext* bgContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [bgContext setPersistentStoreCoordinator:coordinator];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(mergeChanges:) //merge to your main context
                                                 name:NSManagedObjectContextDidSaveNotification
                                               object:bgContext];
    [bgContext performBlock:^{
        //Do somethig with your persistent store data
        //Objects fetched here will only be available for this context
        //And on its own queue
        //Probably need to save & merge to main context so that the fetch results controller will be updated
        //remove the observer
    }];
}

Upvotes: 3

Related Questions