I recently rewrote a database controller based on Core Data to use Grand Central Dispatch to control the extraction and import in the background. The controller can work with 2 NSManagedContext:
NSManagedObjectContext *mainMocinstance variable for the main thread. this context is used only by quick access for the user interface on the main thread or to the dipatch_get_main_queue()global queue.
NSManagedObjectContext *bgMocfor background tasks (data import and selection for NSFetchedresultsController for tables). These background tasks are run ONLY by the user queue: dispatch_queue_t bgQueue(the instance variable in the database controller object).
Data is retrieved for tables in the background so as not to block the user interface when larger or more complex predicates are executed.
Example code fetch for NSFetchedResultsController in table view controllers:
-(void)fetchData{
dispatch_async([CDdb db].bgQueue, ^{
NSError *error = nil;
[[self.fetchedResultsController fetchRequest] setPredicate:self.predicate];
if (self.fetchedResultsController && ![self.fetchedResultsController performFetch:&error]) {
NSSLog(@"Unresolved error in fetchData %@", error);
}
if (!initial_fetch_attampted)initial_fetch_attampted = YES;
fetching = NO;
dispatch_async(dispatch_get_main_queue(), ^{
[self.table reloadData];
[self.table scrollRectToVisible:CGRectMake(0, 0, 100, 20) animated:YES];
});
});
} // end of fetchData function p>
bgMoccombined with mainMocwhen saved with NSManagedObjectContextDidSaveNotification:
- (void)bgMocDidSave:(NSNotification *)saveNotification {
dispatch_async(dispatch_get_main_queue(), ^{
[self.mainMoc mergeChangesFromContextDidSaveNotification:saveNotification];
[[NSNotificationCenter defaultCenter] postNotificationName:DATABASE_SAVED_WITH_CHANGES object:saveNotification];
});
}
- (void)mainMocDidSave:(NSNotification *)saveNotification {
dispatch_async(self.bgQueue, ^{
[self.bgMoc mergeChangesFromContextDidSaveNotification:saveNotification];
});
}
The NSfetchedResultsController delegate has only one method implemented (for simplicity):
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
dispatch_async(dispatch_get_main_queue(), ^{
[self fetchData];
});
}
Thus, I try to follow Apple's recommendations for Core Data: 1 NSManagedObjectContext for the stream. I know that this model is not completely clean for two reasons:
bgQueue , , ( , bgMoc NSManagedObjectContext, ).- NSFetchedResultsController bgMoc ( bgQueue), , , .....
95% , ...
:
, . - , - ( ).
( , Xcode).
( ), , - , .
, GCD , , / .
, , ( dispatch_async ). , .
- , , ? , ..
, , , () , NSFetchedResultsController .