Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle NSFetchedResultsController fetch errors?

This is from the Apple sample code:

if (![fetchedResultsController_ performFetch:&error]) {
     /*
      Replace this implementation with code to handle the error appropriately.
      ...
      If it is not possible to recover from the error, ...
      */
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

I am wondering whether it is really necessary to always terminate the app? How could you "replace this implementation with code to handle the error appropriately"? And how would you "recover from the error"?

Any suggestions would be appreciated, Fabian

like image 986
fabian789 Avatar asked Dec 29 '10 18:12

fabian789


1 Answers

Well, apparently nobody has another (better?) solution, so here is my approach:

In my AppController I added a instance variable errorString and this method:

- (void)presentCoreDataError:(NSError *)error
                    withText:(NSString *)text
{
    NSMutableString *localErrorString = [[NSMutableString alloc] init];

    [localErrorString appendFormat:@"Failed to %@: %@", text, [error localizedDescription]];

    NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
    if(detailedErrors != nil && [detailedErrors count] > 0) {
        for(NSError* detailedError in detailedErrors) {
            [localErrorString appendFormat:@"- Detail: %@", [detailedError userInfo]];
        }
    } else {
        [localErrorString appendFormat:@"- %@", [error userInfo]];
    }

    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"Failed to %@", text]
                                                     message:@"Please send a report to the developer."
                                                    delegate:self
                                           cancelButtonTitle:@"Cancel"
                                           otherButtonTitles:@"Send Report", nil] autorelease];
    [alert show];

    self.errorString = localErrorString;
    [localErrorString release];
}

The UIAlertView delegate displays an MFMailComposeViewController with the errorString in the cool courier font :) if "Send Report" is tapped. Otherwise it calls abort():

- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {     // Send Report
        MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
        picker.mailComposeDelegate = self;
        NSArray *toRecipients = [NSArray arrayWithObject:@"[email protected]"];
        [picker setToRecipients:toRecipients];
        [picker setSubject:@"Error Report"];
        [picker setMessageBody:[NSString stringWithFormat:@"The application crashed with the following error:<br><br><FONT FACE=%@> %@ </FONT>", 
                                @"courier", errorString] 
                        isHTML:YES];

        [navigationController presentModalViewController:picker animated:YES];
        [picker release];
    } else {
        abort();
    }
}

And the MFMailComposeViewControllerDelegate displays a second UIAlertView with only one button (obviously the button has index 0, so it will call abort()):

- (void)mailComposeController:(MFMailComposeViewController *)controller
          didFinishWithResult:(MFMailComposeResult)result
                        error:(NSError *)error
{
    [navigationController dismissModalViewControllerAnimated:YES];

    NSMutableString *messageString = [[NSMutableString alloc] init];

    if (result == MFMailComposeResultSent) {
        [messageString appendFormat:@"Thanks! "];
    }

    [messageString appendFormat:@"The application has to quit now."];
    UIAlertView *abortAlert = [[[UIAlertView alloc] initWithTitle:nil
                                                          message:messageString
                                                         delegate:self
                                                cancelButtonTitle:@"OK"
                                                otherButtonTitles:nil] autorelease];

    [abortAlert show];

    [messageString release];
}
like image 77
fabian789 Avatar answered Sep 27 '22 18:09

fabian789