I have a problem that I can’t understand how to handle because does not happen logically.
I have some NSOperations that run concurrently. For example,
- (void)main
{
@autoreleasepool
{
AppDelegate *appController = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = [[NSManagedObjectContext alloc] init];
[self.managedObjectContext setUndoManager:nil];
[self.managedObjectContext setPersistentStoreCoordinator: [appController persistentStoreCoordinator]];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:self.managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Entity" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"%K != %@",@"number1",[NSNumber numberWithInt:2]]];
NSError *error;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *obj in fetchedObjects) {
//Do Something with managed object then save
NSError *error = nil;
//[episode release];
if (![self.managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate.
// You should not use this function in a shipping application, although it may be useful
// during development. If it is not possible to recover from the error, display an alert
// panel that instructs the user to quit the application by pressing the Home button.
//
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
}
- (void)mergeChanges:(NSNotification *)notification
{
AppDelegate *appController = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *mainContext = [appController managedObjectContext];
// Merge changes into the main context on the main thread
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
withObject:notification
waitUntilDone:YES];
}
This is my typical NSOperation, that works concurrently and update my object in the core data, and sometime with no explanation the app crash and I receive that error on this line:
if (![self.managedObjectContext save:&error])
In my crash reports, so my question is, there is a way to prevent the app crash and fix the error? Can I can use a @syncronized when I perform save? Is this due to different threads and different objects? How can I fix this?
Move the code you use to merge changes in the app delegate.
So, within
application:didFinishLaunchingWithOptions:register for the notification.Then, always within the app delegate create your
mergesChanges:method. Here you need to be sure that the notification runs on the main thread and the context you received the notification is different from the main one.P.S. Here you are using a non-concurrent
NSOperationthat, if inserted into aNSOperationQueue, will run in a concurrent manner (the queue, by means of GCD will manage this for you).