Domanda

Sto cercando di visualizzare un UIAlertView in un top-level exception handler iPhone. La funzione di gestione è simile al seguente:

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

Ho visto un codice simile altrove (per esempio, NSSetUncaughtExceptionHandler non cattura tutti gli errori su iPhone ).

Se io passo singolo nel debugger, posso vedere che il gestore di eccezioni si chiama, e posso vedere la schermata corrente dim come se si sta andando per visualizzare l'avviso di fronte ad essa, ma non appare nulla. Al di fuori del debugger, l'applicazione appena si chiude immediatamente e torna alla schermata iniziale del sistema.

Si fa il lavoro se io trappola un errore nel applicationDidFinishLaunching e visualizzare un avviso prima di tornare lì. Suppongo che la vista avviso non ha la possibilità di visualizzare nel gestore di eccezioni, perché l'applicazione sta terminando (al contrario di seduto lì senza far nulla se mi limito a tirare fuori dai guai di applicationDidFinishLaunching). C'è un modo per fare questo lavoro?

È stato utile?

Soluzione

Non so esattamente come [alertView show] è implementato, ma immagino che apporta alcune modifiche alla gerarchia vista e poi si pone per visualizzare l'avviso sul prossimo passaggio attraverso il ciclo di esecuzione (sguardo NSRunLoop).

Ma, dal momento che l'applicazione è in procinto di uscire, il controllo non ritorna al loop corsa, in modo da l'allarme non viene mai visualizzato. È per questo che si vede la fioca dello schermo (l'UIWindow-livello di allerta è immediatamente aggiunto da show), ma l'allarme non viene visualizzata (che sarebbe accaduto nel ciclo di esecuzione).

Se si include [[NSRunLoop currentRunLoop] run] alla fine del vostro gestore di eccezioni, può essere visualizzato l'avviso.

Se si vuole lasciare la vostra applicazione smettere una volta che l'allarme è fatto, probabilmente si può farlo chiamando runUntilDate: di NSRunLoop in un ciclo while, controllando il valore di una bandiera per vedere se l'avviso è stato ancora respinto. In caso affermativo, è sufficiente uscire dalla funzione di gestione e siete a posto. Ciò significa che dovrete impostare un oggetto delegato in allerta che definisce quella bandiera.

Se si vuole lasciare la vostra applicazione continui a funzionare ... lì non sono così sicuro. Si potrebbe semplicemente lasciare che il ciclo di esecuzione continuano a corto di gestore di eccezioni, ma ci potrebbe essere cattivi / strani effetti collaterali di questo. Quindi probabilmente dovreste lasciare che l'applicazione smettere. Inoltre, se si è sicuri di poter recuperare l'eccezione, si dovrebbe avere preso da qualche parte.

Altri suggerimenti

cumuli Grazie alla benzado, ecco quello che penso è un grande gestore di eccezioni di primo livello generico. Sono un principiante così si spera è fatto correttamente, ma funziona:)

Nel mio ... 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;
}

E nella mia ... appDelegate.h:

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

È necessario verificare se viene raggiunto il codice o se semplicemente avete problema di visualizzazione.

NSLog di chiarirà questo.

Se non raggiunta, è necessario impedire l'arresto app, e potrebbe essere necessario un azione ritardata per uscire da tale contesto per la chiamata di allarme:

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

Se si stanno raggiungendo e contesto di esecuzione non è un problema, ma semplicemente non si è visto di allarme, e quindi [avviso] può essere non essere di alto livello sul display. In tal caso, potrebbe essere necessario reindirizzare messaggio via showinview esempio con actionsheet:

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

[actionSheet showInView:topDelegateWindow];
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top