2010-12-29 14 views
10

Questo è dal codice di esempio di Apple:Come gestire gli errori di recupero di 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(); 
} 

Mi chiedo se sia davvero necessario sempre terminare l'applicazione? Come è possibile "sostituire questa implementazione con il codice per gestire l'errore in modo appropriato"? E tu come potresti "recuperare dall'errore"?

Tutti i suggerimenti sarebbero apprezzati, Fabian

+2

Il 'annullare()' la chiamata è lì come una tattica intimidatoria. – BoltClock

+1

In ogni caso, dipenderà da ciò che il controller dei risultati recuperato sta cercando. Ciò significa che per le diverse cose nella tua app dovrai gestire l'errore in modo diverso. La tua domanda su * cosa esattamente fare * con quell'oggetto 'NSError' rimane valido, quindi +1 – BoltClock

+0

tendo a ricevere un avviso sullo schermo che mostra la descrizione localizzata di NSError, in modo che l'utente abbia qualcosa da riferire al supporto tecnico. –

risposta

7

Beh, a quanto pare nessuno ha un altro (meglio?) Soluzione, ecco il mio approccio:

Nel mio AppController ho aggiunto una variabile di istanza errorString e questo metodo:

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

il UIAlertView delegato visualizza un MFMailComposeViewController con il errorString nel font fresco corriere :) se "Send report" è sfruttato. Altrimenti chiama 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(); 
    } 
} 

E i MFMailComposeViewControllerDelegate mostra una seconda UIAlertView con un solo tasto (ovviamente il pulsante ha indice 0, quindi chiamerà 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

Hai usato questa soluzione in produzione? Inoltre, hai mai ricevuto delle e-mail? – abellina

+0

L'ho usato in produzione e ho ricevuto due e-mail. – fabian789

+1

@ fabian789 Ancora utile anni dopo, grazie! Si potrebbe anche voler usare '[MFMailComposeViewController canSendMail]' per determinare se il dispositivo è configurato per l'invio di e-mail (e fornire un messaggio di avviso di fallback se non lo è) prima di inizializzare 'MFMailComposeViewController'. – JWK

Problemi correlati