Maneira correta de sair do aplicativo do iPhone?

Estou programando um aplicativo para iPhone e preciso forçá-lo a sair devido a determinadas ações do usuário. Depois de limpar a memory do aplicativo alocado, qual é o método apropriado para chamar para encerrar o aplicativo?

Você tentou exit(0) ?

Como alternativa, [[NSThread mainThread] exit] , embora eu não tenha tentado, parece a solução mais apropriada.

No iPhone, não há conceito de sair de um aplicativo. A única ação que deve fazer com que um aplicativo seja encerrado é tocar no botão Início no telefone, e isso não é algo que os desenvolvedores tenham access.

De acordo com a Apple, seu aplicativo não deve terminar por conta própria. Como o usuário não accessu o botão “Início”, qualquer retorno para a canvas inicial dá ao usuário a impressão de que seu aplicativo falhou. Isso é confuso, comportamento não padrão e deve ser evitado.

saída (0) aparece para um usuário como falha, então mostre uma mensagem de confirmação para o usuário. Após a confirmação, suspenda (pressione o botão home programaticamente) e aguarde 2 segundos enquanto o aplicativo está indo fundo com animação, em seguida, saia atrás da visão do usuário

 -(IBAction)doExit { //show confirmation message to user UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Confirmation" message:@"Do you want to exit?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil]; [alert show]; } -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex != 0) // 0 == the cancel button { //home button press programmatically UIApplication *app = [UIApplication sharedApplication]; [app performSelector:@selector(suspend)]; //wait 2 seconds while app is going background [NSThread sleepForTimeInterval:2.0]; //exit app when app is in background exit(0); } } 

Não é realmente uma maneira de sair do programa, mas uma maneira de forçar as pessoas a desistirem.

 UIAlertView *anAlert = [[UIAlertView alloc] initWithTitle:@"Hit Home Button to Exit" message:@"Tell em why they're quiting" delegate:self cancelButtonTitle:nil otherButtonTitles:nil]; [anAlert show]; 

Vá para o seu info.plist e verifique a chave “Aplicativo não é executado em segundo plano”. Desta vez, quando o usuário clica no botão home, o aplicativo sai completamente.

Verifique o Q & A aqui: https://developer.apple.com/library/content/qa/qa1561/_index.html

P: Como faço para fechar programaticamente meu aplicativo iOS?

Não há API fornecida para finalizar corretamente um aplicativo iOS.

No iOS, o usuário pressiona o botão Início para fechar os aplicativos. Se o seu aplicativo tiver condições nas quais ele não possa fornecer a function pretendida, a abordagem recomendada é exibir um alerta para o usuário que indique a natureza do problema e as possíveis ações que o usuário pode executar – ativar o WiFi, ativar os Serviços de Localização etc. Permitir que o usuário encerre o aplicativo a seu próprio critério.

AVISO: Não chame a function de exit . Os aplicativos que chamam exit aparecerão para o usuário ter travado, em vez de executar uma finalização normal e voltar à canvas inicial.

Além disso, os dados podem não ser salvos, porque -applicationWillTerminate: e os methods UIApplicationDelegate semelhantes não serão chamados se você chamar exit.

Se durante o desenvolvimento ou teste for necessário terminar sua aplicação, recomenda-se a function abort ou assert macro

adicione a propriedade UIApplicationExitsOnSuspend em application-info.plist para true

Depois de alguns testes, posso dizer o seguinte:

  • usando a interface privada: [UIApplication sharedApplication] fará com que o aplicativo [UIApplication sharedApplication] ter travado, MAS chamará - (void)applicationWillTerminate:(UIApplication *)application antes de fazer isso;
  • usando exit(0); também terminará o aplicativo, mas parecerá “normal” (os icons do trampolim aparecem como esperado, com o efeito de diminuir o zoom), MAS ele não chamará o método de delegação do - (void)applicationWillTerminate:(UIApplication *)application .

Meu conselho:

  1. Chame manualmente o - (void)applicationWillTerminate:(UIApplication *)application no delegado.
  2. Chamar exit(0); .

Seu ApplicationDelegate é notificado de desistir intencionalmente pelo usuário:

 - (void)applicationWillResignActive:(UIApplication *)application { 

Quando recebo esta notificação, acabei de ligar

  exit(0); 

Qual faz todo o trabalho. E a melhor coisa é que é a intenção dos usuários de sair, e é por isso que isso não deve ser um problema em chamá-lo para lá.

No meu Audio-App, foi necessário sair do aplicativo depois que as pessoas estavam sincronizando o dispositivo enquanto a música ainda estava sendo reproduzida. Assim que a synchronization terminar, recebo uma notificação. Mas sair do aplicativo logo depois disso seria realmente um acidente.

Então, em vez disso, defini um sinalizador para REALMENTE sair do aplicativo na próxima ação de plano de fundo. O que é certo para atualizar o aplicativo depois de uma synchronization.

Meu App foi rejeitado recentemente bc Eu usei um método não documentado. Literalmente:

“Infelizmente, ele não pode ser adicionado à App Store porque ele está usando uma API privada. O uso de APIs não públicas, como descrito na seção 3.3.1 do Contrato de Licença do Programa para Desenvolvedores do iPhone, é proibido:

“3.3.1 Os aplicativos podem usar apenas APIs documentadas da maneira prescrita pela Apple e não devem usar ou chamar qualquer API privada.”

A API não pública incluída em seu aplicativo é terminateWithSuccess ”

Apple diz:

“Aviso: Não chame a function de saída. Os aplicativos que chamam exit serão exibidos para o usuário ter travado, em vez de executar uma finalização normal e voltar à canvas inicial.”

Eu acho que isso é uma suposição ruim. Se o usuário tocar em um botão de sair e aparecer uma mensagem dizendo algo como: “O aplicativo será encerrado agora”, ele não parece estar com falha. A Apple deve fornecer uma maneira válida de encerrar um aplicativo (não sair (0)).

Isso obteve uma boa resposta, mas decidiu expandir um pouco:

Você não pode ter seu aplicativo aceito na AppStore sem ler as Diretrizes de interface humana do iOS da Apple. (Eles mantêm o direito de rejeitá-lo por fazer algo contra eles). A seção “Não pare programaticamente” http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices. html é uma diretriz exata de como você deve tratar neste caso.

Se você tiver algum problema com a plataforma Apple, não poderá encontrar facilmente uma solução para, consulte a HIG. É possível que a Apple simplesmente não queira que você faça isso e eles geralmente (eu não sou a Apple, então eu não posso garantir sempre) dizem na sua documentação.

Não podemos sair do aplicativo usando exit(0) funções exit(0) e abort() , pois a Apple não recomenda o uso dessas funções. Embora você possa usar essas funções para fins de desenvolvimento ou teste.

Se durante o desenvolvimento ou teste for necessário terminar sua aplicação, recomenda-se a function abortar ou assert macro

Por favor, encontre este tópico da Apple Q & A para obter mais informações.

Conforme o uso dessa function, crie impressões como se o aplicativo estivesse falhando. Então eu tenho alguma sugestão como podemos exibir alerta com mensagem de rescisão para o usuário ciente sobre o fechamento do aplicativo, devido à indisponibilidade de certas funcionalidades.

Mas iOS interface de interface humana para iniciar e parar App , sugerindo que nunca use o botão Sair ou Fechar para encerrar o aplicativo. Em vez disso, eles estão sugerindo que mostrem a mensagem apropriada para explicar a situação.

Um aplicativo para iOS nunca exibe uma opção Fechar ou Sair. As pessoas param de usar um aplicativo quando mudam para outro aplicativo, retornam à canvas inicial ou colocam seus dispositivos no modo de suspensão.

Nunca saia de um aplicativo iOS programaticamente. As pessoas tendem a interpretar isso como um acidente. Se algo impedir que seu aplicativo funcione conforme planejado, você precisará informar os usuários sobre a situação e explicar o que eles podem fazer a respeito.

Além do acima, boa resposta, eu só queria adicionar, pense em limpar sua memory.

Depois que o aplicativo for encerrado, o iPhone OS limpará automaticamente tudo o que seu aplicativo deixou para trás, portanto, liberar toda a memory manualmente pode aumentar o tempo que o aplicativo leva para sair.

Hm, você pode ‘ter que’ sair do aplicativo se, digamos, seu aplicativo exigir uma conexão com a Internet. Você pode exibir um alerta e fazer algo assim:

 if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) { [[UIApplication sharedApplication] performSelector:@selector(terminate)]; } else { kill(getpid(), SIGINT); } 
 - (IBAction)logOutButton:(id)sender { //show confirmation message to user CustomAlert* alert = [[CustomAlert alloc] initWithTitle:@"Confirmation" message:@"Do you want to exit?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil]; alert.style = AlertStyleWhite; [alert setFontName:@"Helvetica" fontColor:[UIColor blackColor] fontShadowColor:[UIColor clearColor]]; [alert show]; } - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex != 0) // 0 == the cancel button { //home button press programmatically UIApplication *app = [UIApplication sharedApplication]; [app performSelector:@selector(suspend)]; //wait 2 seconds while app is going background [NSThread sleepForTimeInterval:2.0]; //exit app when app is in background NSLog(@"exit(0)"); exit(0); } } 

Eu usei a abordagem [[NSMutableArray new] addObject: nil] mencionada acima para forçar o encerramento (falha) do aplicativo sem fazer uma chamada de function exit (0) avisadora.

Por quê? Porque meu aplicativo usa a fixação de certificados em todas as chamadas de API de rede para impedir ataques man-in-the-middle. Estas incluem as chamadas de boot que meu aplicativo financeiro faz na boot.

Se a autenticação de certificado falhar, todas as minhas chamadas de boot serão eliminadas e deixarão meu aplicativo em um estado indeterminado. Deixar o usuário ir para casa e voltar ao aplicativo não ajuda, já que, a menos que o aplicativo tenha sido removido pelo sistema operacional, ele ainda não foi inicializado e não é confiável.

Assim, neste caso, achamos melhor estourar um alerta informando ao usuário que o aplicativo está operando em um ambiente inseguro e, em seguida, ao clicar em “Fechar”, forçar o encerramento do aplicativo usando o método mencionado anteriormente.

Sair de um aplicativo de outra forma que o botão home é realmente uma abordagem não-iOS-esque .

Eu fiz esse ajudante, no entanto, que não usa nada particular:

 void crash() { [[NSMutableArray new] addObject:NSStringFromClass(nil)]; } 

Mas ainda não é para produção no meu caso. É para testar relatórios de falhas ou para reinicializar rapidamente após uma redefinição de Core Data. Apenas tornou seguro não ser rejeitado se a function fosse deixada no código de produção.

O usuário deve decidir quando um aplicativo sai. Não acho que seja uma boa interação do usuário quando um aplicativo é encerrado. Portanto, não há uma API boa para isso, apenas o botão home tem um.

Se houver um erro: implemente-o melhor ou notifique o usuário. Se tiver que haver uma reboot: Implemente melhor Notificar o usuário.

Parece estúpido, mas é uma prática ruim sair do aplicativo sem permitir que o usuário decida e não o notifique. E como há um botão inicial para a interação do usuário, a Apple afirma que não deve haver duas coisas para a mesma function (saindo de um aplicativo).

Sair de um aplicativo de outra forma

Eu fiz esse ajudante, no entanto, que não usa nada particular:

Saída (0);

Pode ser apropriado sair de um aplicativo se for um aplicativo de longa duração que também é executado em segundo plano, por exemplo, para obter atualizações de local (usando o recurso de atualização de local para isso).

Por exemplo, digamos que o usuário faça o logout do seu aplicativo baseado em localização e envie o aplicativo para o segundo plano usando o botão “Início”. Nesse caso, seu aplicativo pode continuar em execução, mas pode fazer sentido sair completamente dele. Seria bom para o usuário (libera memory e outros resources que não precisam ser usados), e bom para a estabilidade do aplicativo (ou seja, garantir que o aplicativo seja reiniciado periodicamente quando possível é uma rede de segurança contra vazamentos de memory e outros problemas de memory). problemas).

Isso poderia (embora provavelmente não deveria, ver abaixo 🙂 ser alcançado com algo como:

 - (void)applicationDidEnterBackground:(UIApplication *)application { if (/* logged out */) { exit(0); } else { // normal handling. } } 

Como o aplicativo sairia do segundo plano, ele não pareceria errado para o usuário e não se assemelharia a uma falha, desde que a interface do usuário seja restaurada na próxima vez em que ele executar o aplicativo. Em outras palavras, para o usuário, não seria diferente de um término iniciado pelo aplicativo quando o aplicativo estivesse em segundo plano.

Ainda assim, seria preferível usar uma abordagem mais padrão para informar ao sistema que o aplicativo pode ser encerrado. Por exemplo, neste caso, certificando-se o GPS não está em uso, parando de solicitar atualizações de localização, incluindo desligar mostrar a localização atual em um mapa, se presente. Dessa forma, o sistema cuidará de encerrar o aplicativo por alguns minutos (ou seja, [[UIApplication sharedApplication] backgroundTimeRemaining] ) após o aplicativo entrar em segundo plano. Isso teria todos os mesmos benefícios sem ter que usar o código para encerrar o aplicativo.

 - (void)applicationDidEnterBackground:(UIApplication *)application { if (/* logged out */) { // stop requesting location updates if not already done so // tidy up as app will soon be terminated (run a background task using beginBackgroundTaskWithExpirationHandler if needed). } else { // normal handling. } } 

E, claro, usar exit(0) nunca seria apropriado para o aplicativo de produção médio que é executado em primeiro plano, como outras respostas que fazem referência a http://developer.apple.com/iphone/library/qa/qa2008/qa1561. html

 [[UIApplication sharedApplication] terminateWithSuccess]; 

Funcionou bem e chama automaticamente

 - (void)applicationWillTerminateUIApplication *)application delegate. 

para remover aviso de tempo de compilation adicionar este código

 @interface UIApplication(MyExtras) - (void)terminateWithSuccess; @end