Pergunta

Estou tentando exibir um UialerTView em um manipulador de exceção do iPhone de nível superior. A função do manipulador se parece com o seguinte:

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

Eu já vi código semelhante em outro lugar (por exemplo, Nssetuncaughtexceptionhandler não pegue todos os erros no iPhone).

Se eu for uma etapa única no depurador, posso ver que o manipulador de exceção é chamado e posso ver a tela atual como se ela exibisse o alerta na frente dela, mas nada aparece. Fora do depurador, o aplicativo desiste imediatamente e volta à tela inicial do sistema.

Funciona se eu prender um erro no ApplicationDidFinishLaunching e exibir um alerta antes de retornar. Suponho que a visão de alerta nunca tenha a chance de exibir o manipulador de exceção porque o aplicativo está terminando (em vez de ficar sentado sem fazer nada se eu apenas resgatar o aplicativoDIDFINISHLAUNCHING). Existe uma maneira de fazer isso funcionar?

Foi útil?

Solução

Eu não sei exatamente como [alertView show] é implementado, mas imagino que isso faça algumas alterações na hierarquia de visualizações e depois se define para exibir o alerta no próximo passe pelo loop de corrida (procure para cima NSRunLoop).

Mas, como o aplicativo está prestes a sair, o controle não retorna ao loop de corrida, o alerta nunca é exibido. É por isso que você vê a tela escura (o UiWindow no nível de alerta é imediatamente adicionado por show) Mas o alerta não aparece (isso aconteceria no loop de corrida).

Se você incluir [[NSRunLoop currentRunLoop] run] No final do seu manipulador de exceção, o alerta pode aparecer.

Se você quiser deixar seu aplicativo sair assim que o alerta estiver pronto, você provavelmente pode fazê -lo ligando para o NSrunloop's runUntilDate: Em um loop de tempo, verificando o valor de uma bandeira para ver se o alerta foi demitido ainda. Se tiver, basta sair da função do manipulador e você estará pronto. Isso significa que você terá que definir um objeto delegado no alerta que define esse sinalizador.

Se você quiser deixar seu aplicativo continuar correndo ... lá não tenho tanta certeza. Você pode deixar o loop de corrida continuar ficando sem o manipulador de exceção, mas pode haver efeitos colaterais ruins/estranhos nisso. Então você provavelmente deve deixar o aplicativo sair. Além disso, se você tem certeza de que pode se recuperar da exceção, deveria ter pego em algum lugar.

Outras dicas

Obrigado Woaps to Benzado, eis o que eu acho que é um ótimo gerente de exceção genérico de nível superior. Eu sou um iniciante, então espero que seja feito corretamente, mas funciona :)

No meu ... 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 no meu ... appdelegate.h:

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

Você deve verificar se o código é atingido ou se você apenas possui um problema de exibição.

O NSLog vai esclarecer isso.

Se não for alcançado, você precisa evitar o desligamento do aplicativo e pode precisar de uma ação atrasada para sair desse contexto para a chamada de alerta:

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

Se você estiver atingindo e o contexto de execução não é um problema, mas você simplesmente não está vendo alerta, o [Alert Show] pode não estar no nível superior em exibição. Nesse caso, pode ser necessário redirecionar a mensagem via ShowInview, por exemplo, com o ActionSheet:

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

[actionSheet showInView:topDelegateWindow];
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top