Reputation: 1
I am facing an issue dealing with when I download large data (using url pagination) from the internet and sav it in core data. During saving of the data my apps GUI becomes frozen. After saving the data my app works normally. I need your help with how can I remove the app freezing up issue.
I am downloading the data using NSURLConnection
delegate method which is asynchronous. In connectionDidFinishLoading
method I am inserting the data in core data. This is the code inside connectionDidFinishLoading
method.
[Customer insertCustomerWithList:data];
[self.delegate connectPermissionServiceSuccessful:method];
Here on insertCustomerWithList
method application becomes frozen.
If I use the dispatch_async
GCD approach then the application starts to crash by giving this error.
ERROR*** Collection <NSCFSet: 0x7c2282e0> was mutated while being enumerated.
This is the code with GCD.
dispatch_queue_t coreDataThread = dispatch_queue_create("com.YourApp.YourThreadName", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(coreDataThread, ^{
[Customer insertCustomerWithList:data];
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate connectPermissionServiceSuccessful:kMethod];
});
});
This is the insertCustomerWithList
method which is inserting the data in core data.
+ (BOOL) insertCustomerWithList:(NSArray*)customerList
`{NSError *error = nil;
BOOL success = YES;
Customer *obj = nil;
NSManagedObjectContext *managedObjectContext = [NSManagedObjectContext managedObjectContext];`
if (managedObjectContext == nil)
{
success = NO;
}
@try
{
for (NSInteger index = 0; index < customerList.count ; index ++)
{
NSDictionary* customerInfo = customerList[index];
obj = [self getCustomerByID:customerInfo[@"_id"]];
if (obj == nil)
{
obj = [NSEntityDescription insertNewObjectForEntityForName:kEntityName
inManagedObjectContext:managedObjectContext];
[obj updateCustomer:customerInfo];
}
else
{
[obj updateCustomer:customerInfo];
}
}
}
@catch (NSException *exception)
{
NSLog(@"__ERROR__%@__", exception.reason);
}
[managedObjectContext save:&error];
return success;
`}`
Please help with how I can fix this issue.
Upvotes: 0
Views: 679
Reputation: 7552
It's hard to give a specific answer, as you don't show how your Core Data stack is arranged.
For a basic app, the simplest approach is to create a persistent background context (NSPrivateQueueConcurrencyType
) which is connected to the persistent store. For the main thread, create a child of your background context with NSMainQueueConcurrencyType
.
You do the writing on the background context by issuing it a performBlock
message. You can be notified in the child context by setting up an NSFetchedResultsController.
Upvotes: 0
Reputation: 80273
You should be using NSManagedObjectContext
's performBlock
APIs rather than creating your own thread.
The following setup will not block your UI:
Root context (background) - save to persistent store
Main context (foreground) - child of Root, used on UI
Worker context (background) - child of Main, do heavy loading
The result block of your web call should create a worker context and insert the new data. Then the save()
method will "push" the changes up to the main context, so if your UI needs to display the new data, that is already possible. The main context's save()
pushes the changes to the root context and only when you call save()
on the root context the changes are written to the database.
Use the block APIs for the background operations and you will be fine.
Upvotes: 2