2010-12-29 12 views
10

Esto es desde el código de ejemplo de Apple:Cómo manejar los errores de recuperación de NSFetchedResultsController?

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(); 
} 

Me pregunto si es realmente necesario siempre terminar la aplicación? ¿Cómo podría "reemplazar esta implementación con código para manejar el error apropiadamente"? ¿Y cómo se recuperaría "del error"?

Cualquier sugerencia sería apreciada, Fabian

+2

El 'abortar()' la llamada está ahí como una táctica de miedo. – BoltClock

+1

De todos modos, dependería de lo que esté buscando el controlador de resultados obtenidos. Eso significa que para diferentes cosas en su aplicación querrá manejar el error de manera diferente. Su pregunta sobre * qué es exactamente lo que debe hacer * con ese objeto 'NSError' sigue siendo válida, así que +1 – BoltClock

+0

Tiendo a recibir una alerta en la pantalla que muestra la descripción localizada de NSError, para que el usuario tenga algo que informar al soporte técnico. –

Respuesta

7

Bueno, al parecer nadie ha otra solución (mejor?), Así que aquí está mi enfoque:

En mi AppController He añadido una variable de instancia errorString y este método:

- (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]; 
} 

el delegado UIAlertView muestra un MFMailComposeViewController con el errorString en la fuente fresca de mensajería :) si "Enviar informe" se dio un golpecito. De lo contrario se llama 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(); 
    } 
} 

Y los MFMailComposeViewControllerDelegate muestra una segunda UIAlertView con un solo botón (obviamente, el botón tiene el índice 0, por lo que llamará 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]; 
} 
+0

¿Ha utilizado esta solución en producción? Además, ¿alguna vez has recibido algún correo electrónico? – abellina

+0

Lo he usado en producción y he recibido dos correos electrónicos. – fabian789

+1

@ fabian789 Todavía útiles años después, ¡gracias! También puede usar '[MFMailComposeViewController canSendMail]' para determinar si el dispositivo está configurado para enviar correos electrónicos (y proporcionar un mensaje de alerta de respaldo si no es así) antes de inicializar 'MFMailComposeViewController'. – JWK

Cuestiones relacionadas