14

In my app I am getting a bunch of SIGABRT crash reports (from specific users) due to this core data save error handling code:

NSError *error = nil;
if (![moc save:&error])
{
    if(error)
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}

Is there a better way to handle core data save error than terminating the process using abort()?

Nikos M.
  • 13,685
  • 4
  • 47
  • 61

3 Answers3

6

Based on the fact a save error should not appear in production my best advice is to follow a similar pattern.

NSError *error = nil;
if ([self.managedObjectContext save:&error] == NO) {
    NSAssert(NO, @"Save should not fail");
    [self showAlert];
}

- (void)showAlert {
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Could Not Save Data"
                                                        message:@"There was a problem saving your data but it is not your fault. If you restart the app, you can try again. Please contact support (support@domain.com) to notify us of this issue."
                                                       delegate:self
                                              cancelButtonTitle:@"Ok"
                                              otherButtonTitles:nil];
    [alertView show];
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
    abort();
}

Credits goes to Matthew Morey as described in NSManagedObjectContext save error.

I really like this approach since it informs the user that something bad happened. In addition to this I will also create a log file that can be sent by email to support. In the log you will put much info as possible to investigate the error. To achieve this, for example, you could use CocoaLumberjack. Take a look also to Mailing Logs by NSSCreenCast.

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
  • Can I completely avoid the abort() thing in some way? – Nikos M. Mar 13 '14 at 16:05
  • 4
    I disagree that a save should not fail in production. A save may fail if the object didn't pass validation or violates referential integrity rules. One cannot always achieve object validation in UI code. Showing the user that something went wrong and then aborting doesn't really help the user. Depending on the circumstances, the program should _rollback_ the context to a _logical correct_ state, and then _replay_ the actions which lead to this error, assuming that this can eventually succeed, or will be cancelled by the user. – CouchDeveloper Mar 13 '14 at 17:10
  • @CouchDeveloper I think Marcus Zarra will dissappoint this. ;) I usually do not use validation in Core Data. Only at application level. It is easier to maintain. – Lorenzo B Mar 13 '14 at 17:15
  • ...waiting for @MarcusS.Zarra tips. – Lorenzo B Mar 13 '14 at 17:15
  • In addition showing an alert it's not simply aborting the app. I also suggested to log to a file... – Lorenzo B Mar 13 '14 at 17:17
  • @CouchDeveloper: Do you have any better Code for Core Data error handling than the snippets shown here? I already try to keep my context clean by deleting objects if a save fails but creating multiple objects with relationships make things more tricky. Was thinking about using rollback but that could by accident rollback valid changes as well :/ BR Chris – cschuff Sep 03 '14 at 10:34
  • @CouchDeveloper Posted my solution here: http://stackoverflow.com/questions/2262704/iphone-core-data-production-error-handling/25643856#25643856 – cschuff Sep 03 '14 at 12:06
  • Asserts and aborts are how developers think. Let the designer decide how this one goes down. A save could fail because your device run out of storage space. Just tell the user with UI. Maybe with a cat meme? Give them a chance to free up space on their device. Maybe the cat is happy when they return, does a dance animation then your App returns to it's original state. –  Jun 24 '17 at 09:41
4

So Core Data actually provides you with a lot of information about why it couldn't save or why validation failed. You can extract that information and present it to the user in a helpful way and let him/her fix it (in case we are talking about user-generated data). Here's a solution I've come up with: iPhone Core Data "Production" Error Handling

Community
  • 1
  • 1
Johannes Fahrenkrug
  • 42,912
  • 19
  • 126
  • 165
  • That's a useful code snippet! The next step is then to associate the error message to the input field in the UI, place a red exclamation mark beneath it, and when the user tabs on it, a nice sheet pops up with detailed info about the error ;) – CouchDeveloper Mar 13 '14 at 13:42
  • @CouchDeveloper That would indeed be fantastic! Then we would have Ruby on Rails behavior :) That sounds like an idea for a very useful Open Source project! – Johannes Fahrenkrug Mar 13 '14 at 13:45
  • Same thoughts, here ... ;) – CouchDeveloper Mar 13 '14 at 13:50
-1

Use this code sure it will help you

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            abort();
        }
    }
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Javid
  • 343
  • 1
  • 2
  • 12