How to handle NSFetchedResultsController fetch errors?
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:@"first@example.com"]; [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];}