I am using multithreading while loading data from the database.
I am doing the following
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
// Get data
NSDate *pastDate = [CommonHelper getSelectedDateYearBackComponents:[NSDate date]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"users == %@ && startDate >= %@", objUser,pastDate];
NSMutableArray *fetchArray = [DataAccess searchObjectsInUserContext:@"userIngo" :predicate :@"startDate" :NO];
if ([fetchArray count] > 0)
{
dispatch_async(dispatch_get_main_queue(),
^{
// Reload table
[self.tableView reloadData]; });
}
else
{
dispatch_async(dispatch_get_main_queue(),
^{ // calling Webservice
});
}
});
where users is the entity from which I am trying to fetch data and objUser is the user object for whom I am retrieving data from the users entity
and my searchObjectsInUserContext code is like this
+(NSMutableArray *) searchObjectsInLabContext: (NSString*) entityName : (NSPredicate *) predicate : (NSString*) sortKey : (BOOL) sortAscending
{
i3EAppDelegate *appDelegate = (i3EAppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setUndoManager:nil];
[context setPersistentStoreCoordinator:[appDelegate persistentStoreCoordinator]];
// Register context with the notification center
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[request setEntity:entity];
[request setFetchBatchSize:10];
[request setReturnsObjectsAsFaults:NO];
// If a predicate was passed, pass it to the query
if(predicate != nil)
{
[request setPredicate:predicate];
}
// If a sort key was passed, use it for sorting.
if(sortKey != nil)
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:sortAscending];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];
}
NSError *error;
NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) {
// Handle the error.
// NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
[request release];
appDelegate = nil;
return [mutableFetchResults autorelease];
}
So in my searchObjectInUserContext I use multiple managedObjectContext so that it does not create problems for me while multithreading as explained by Fred McCann in his blog post.
However, my problem is at NSMutableArray *mutableFetchResults in my searchObjectsInUserContext because it returns 0 at times even though there is data in the database.
Can someone help me with what I am doing wrong?
Update
There is nothing wrong with your fetch so I suspect the issue might be one of timing. Is this fetch being run before another thread saves? That would explain the behavior you are seeing.
Also, why are you running this on a background thread? Are you seeing a performance issue that requires a background search like this?
Update 2
First, I still question the need for the background fetching. That is normally reserved for when you have performance issues as fetching is very fast.
Second, you fetch on a background queue but then you don’t do anything with the data you fetched. You do not hand it off to the table (which would be bad anyway) you just fetch and throw it away.
If you are fetching just to count then don’t fetch, do a
-[NSManagedObjectContext -countForFetchRequest: error:]. It will be even faster and removes the need for the background queue call.If you are expecting to do something with the results you have an issue. Instances of
NSManagedObjectcannot cross a thread/queue boundary. So fetching on the background queue does very little for the UI. You need to fetch those objects on the main queue/main thread. If you don’t you will crash because Core Data does not allow it.In the end, your background queues are doing you more harm than good and they are not solving the problem you are trying to solve.