Question

Je suis en train d'afficher un UIAlertView dans un gestionnaire d'exception iPhone haut niveau. La fonction de gestionnaire ressemble à ceci:

void applicationExceptionHandler(NSException *ex) {
  UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"
                                                      message:[ex reason]
                                                      delegate:nil
                                             cancelButtonTitle:@"OK"
                                             otherButtonTitles:nil];
  [alertView show];
}

Je l'ai vu ailleurs un code similaire (par exemple, NSSetUncaughtExceptionHandler pas attraper toutes les erreurs sur iPhone ).

Si je une seule étape dans le débogueur, je peux voir que le gestionnaire d'exception est appelé, et je peux voir l'écran en cours dim comme si elle va afficher l'alerte devant, mais rien ne semble. En dehors du débogueur, l'application se ferme juste immédiatement et retourne à l'écran d'accueil du système.

Il fonctionne si je piège une erreur dans applicationDidFinishLaunching et afficher une alerte avant de retourner. Je suppose que l'affichage des alertes ne devient jamais une chance d'afficher dans le gestionnaire d'exception, car l'application se termine (par opposition à rien assis faire là-bas si je viens de liberté sous caution de applicationDidFinishLaunching). Y at-il un moyen de faire ce travail?

Était-ce utile?

La solution

Je ne sais pas exactement comment [alertView show] est mis en œuvre, mais je pense qu'il fait quelques modifications à la hiérarchie de la vue et se fixe pour afficher l'alerte sur la passe suivante dans la boucle d'exécution (look up NSRunLoop).

Mais, puisque l'application est sur le point de quitter, le contrôle ne retourne pas à la boucle d'exécution, de sorte que l'alerte est jamais affichée. Voilà pourquoi vous voyez les dim d'écran (par le show UIWindow est ajouté immédiatement au niveau d'alerte), mais l'alerte n'apparaît pas (que se passerait-il dans la boucle d'exécution).

Si vous ajoutez [[NSRunLoop currentRunLoop] run] à la fin de votre gestionnaire d'exception, l'alerte peut apparaître.

Si vous voulez laisser votre application quitter une fois que l'alerte est fait, vous pouvez probablement le faire en appelant runUntilDate: de NSRunLoop dans une boucle while, vérifier la valeur d'un drapeau pour voir si l'alerte a encore été rejetée. Si elle a, quittez simplement la fonction de gestionnaire et vous êtes bon pour aller. Cela signifie que vous devrez définir un objet délégué sur l'alerte qui établit le drapeau.

Si vous voulez laisser votre application continuer de courir ... là, je ne suis pas si sûr. Vous pouvez simplement laisser la boucle d'exécution continue à manquer du gestionnaire d'exception, mais il pourrait y avoir des effets secondaires mauvais / étranges à cela. Donc, vous devriez probablement laisser l'application quitter. D'ailleurs, si vous êtes sûr que vous pouvez récupérer de l'exception, vous devriez avoir attrapé quelque part.

Autres conseils

tas Merci à benzado, voici ce que je pense est un gestionnaire d'exception générique de premier niveau. Je suis un débutant si nous espérons qu'il est fait correctement, mais il ne fonctionne pas:)

Dans mon ... appDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{        
    [window makeKeyAndVisible];

    NSSetUncaughtExceptionHandler(&exceptionHandler);

    return YES;
}

BOOL exceptionAlertDismissed = FALSE;
void exceptionHandler(NSException *exception)
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"App Committed Suicide"
        message:@"Oh dear, that wasn't supposed to happen. You will have to restart the application... sorry!"
        delegate:[[UIApplication sharedApplication] delegate] cancelButtonTitle:nil otherButtonTitles:@"That's ok!", @"Erm, bye...", nil];
    [alert show];
    [alert release];

    while (exceptionAlertDismissed == FALSE)
    {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    exceptionAlertDismissed = TRUE;
}

Et dans mon ... appDelegate.h:

@interface ...appDelegate : NSObject <UIApplicationDelegate, UIAlertViewDelegate>
...
void exceptionHandler(NSException *exception);

Vous devez vérifier si le code est atteinte ou si vous avez juste problème d'affichage.

NSLog de précisera que.

Si pas atteint, vous avez besoin d'empêcher l'arrêt de l'application, et vous devrez peut-être une action retardée pour sortir de ce contexte pour l'appel d'alerte:

[self performSelector: @selector(showAlert:) withObject:@"msg" afterDelay: 0.1];

Si vous atteignez et contexte d'exécution n'est pas un problème, mais vous ne voyez pas simplement alerte, [show alerte] peut être ne pas être plus haut niveau dans l'affichage. Dans ce cas, vous devrez peut-être rediriger message via showinview par exemple avec actionsheet:

topDelegate=[[UIApplication sharedApplication] delegate];
topDelegateWindow=[topDelegate.window.subviews objectAtIndex:0];

[actionSheet showInView:topDelegateWindow];
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top