Maneira adequada de sair do aplicativo para iPhone?
-
21-08-2019 - |
Pergunta
Estou programando um aplicativo para iPhone e preciso forçá -lo a sair devido a determinadas ações do usuário. Depois de limpar a memória que o aplicativo alocado, qual é o método apropriado para encerrar o aplicativo?
Solução
Você tentou exit(0)
?
Alternativamente, [[NSThread mainThread] exit]
, embora eu não tenha tentado que pareça a solução mais apropriada.
Outras dicas
No iPhone, não há conceito de desistir de um aplicativo. A única ação que deve fazer com que um aplicativo saia é tocar no botão doméstico no telefone, e isso não é algo a que os desenvolvedores tenham acesso.
Segundo a Apple, seu aplicativo não deve terminar por conta própria. Como o usuário não atingiu o botão home, qualquer retorno à tela inicial dá ao usuário a impressão de que seu aplicativo travou. Isso é um comportamento confuso e não padrão e deve ser evitado.
A saída (0) aparece para um usuário como falhas, então mostre uma mensagem de confirmação ao usuário. Após a confirmação, suspenda (botão doméstico pressione programaticamente) e aguarde 2 segundos enquanto o aplicativo está em segundo plano com animação e depois saia atrás da visualizaçã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 desistir.
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];
Verifique as perguntas e respostas aqui: https://developer.apple.com/library/content/qa/qa1561/_index.html
P: Como faço para sair programaticamente do meu aplicativo iOS?
Não há API fornecida para encerrar graciosamente um aplicativo iOS.
No iOS, o usuário pressiona o botão doméstico para fechar aplicativos. Se o seu aplicativo tiver condições nas quais não pode fornecer sua função pretendida, a abordagem recomendada é exibir um alerta para o usuário que indica a natureza do problema e as ações possíveis que o usuário poderia executar - ativando o WiFi, permitindo serviços de localização etc. Permita que o usuário encerre o aplicativo a seu próprio critério.
AVISO: Não ligue para o
exit
função. CHAMADA DE APLICAÇÕESexit
Parece que o usuário travou, em vez de realizar uma rescisão graciosa e animar de volta à tela inicial.Além disso, os dados não podem ser salvos, porque
-applicationWillTerminate:
e semelhanteUIApplicationDelegate
Os métodos não serão invocados se você ligar para a saída.Se durante o desenvolvimento ou teste, for necessário encerrar sua aplicação, o
abort
função, ouassert
Macro é recomendado
Vá para sua info.plist e verifique a chave "o aplicativo não é executado em segundo plano". Desta vez, quando o usuário clica no botão doméstico, o aplicativo sai completamente.
Adicionar UIApplicationExitsOnSuspend
propriedade em application-info.plist
para true
.
Após alguns testes, posso dizer o seguinte:
- Usando a interface privada:
[UIApplication sharedApplication]
fará com que o aplicativo pareça travado, mas vai ligar- (void)applicationWillTerminate:(UIApplication *)application
antes de fazê -lo; - usando
exit(0);
também terá encerrar o aplicativo, mas parecerá "normal" (os ícones do trampolim parecem esperados, com o efeito de zoom), mas não chamará o- (void)applicationWillTerminate:(UIApplication *)application
Método delegado.
Meu conselho:
- Ligue manualmente para o
- (void)applicationWillTerminate:(UIApplication *)application
no delegado. - Ligar
exit(0);
.
Seu ApplicationDelegate é notificado de desistir intencional pelo usuário:
- (void)applicationWillResignActive:(UIApplication *)application {
Quando recebo esta notificação, apenas ligo
exit(0);
Que faz todo o trabalho. E a melhor coisa é que é a intenção de sair, e é por isso que isso não deve ser um problema de chamá -lo lá.
No meu aplicativo de áudio, era necessário sair do aplicativo depois que as pessoas estavam sincronizando o dispositivo enquanto a música ainda estava tocando. Assim que a sincronização estiver completa, recebo uma notificação. Mas deixar o aplicativo logo depois disso pareceria uma falha.
Então, em vez disso, defino um sinalizador para realmente sair do aplicativo na próxima ação de fundo. O que é bom para atualizar o aplicativo após uma sincronização.
Meu aplicativo foi rejeitado recentemente bc Eu usei um método sem documentos. Literalmente:
"Infelizmente, ele não pode ser adicionado à App Store porque está usando uma API privada. Uso de APIs não públicas, que, conforme descrito no contrato de licença do Programa de Desenvolvedor de Iphone, a Seção 3.3.1 é proibida:
"3.3.1 Os aplicativos podem usar apenas APIs documentadas da maneira prescrita pela Apple e não devem usar ou chamar nenhuma API privada".
A API não pública que está incluída em seu aplicativo é encerrada com o sucesso "
Apple diz:
"Aviso: não chame a função de saída. Os aplicativos que chamam de saída aparecerão para o usuário ter falhado, em vez de executar uma rescisão graciosa e animar de volta à tela inicial".
Eu acho que isso é uma má suposição. Se o usuário tocar em um botão desistir e aparecer uma mensagem que diga algo como: "O aplicativo agora desistirá.", Ele não parece estar travado. A Apple deve fornecer uma maneira válida de sair de um aplicativo (não saída (0)).
Isso obteve uma boa resposta, mas decidiu expandir um pouco:
Você não pode aceitar seu aplicativo no AppStore sem ler bem as diretrizes da interface humana do iOS da Apple. (Eles mantêm o direito de rejeitá -lo por fazer nada 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 em como você deve tratar neste caso.
Se você tiver um problema com a plataforma da Apple, não pode encontrar facilmente uma solução, consulte o HIG. É possível que a Apple simplesmente não quer que você faça isso e eles geralmente (eu não sou maçã, então não posso garantir sempre) o dizem na documentação deles.
Não podemos sair do aplicativo usando exit(0)
, abort()
Funções, como a Apple desencoraja fortemente 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 encerrar sua aplicação, a função de aborto ou a macro afirma
Por favor, encontre esta maçã Q&A Tópico para obter mais informações.
Como o uso dessa função, crie impressão como o aplicativo está travando. Então, recebi algumas sugestões como podemos exibir a mensagem de terminação para conscientizar o usuário sobre o fechamento do aplicativo, devido à indisponibilidade de certa funcionalidade.
Mas a diretriz de interface humana do iOS para Aplicativo de partida e parada, sugerindo que Nunca use o botão de sair ou fechar Para encerrar a aplicação. Em vez disso, eles estão sugerindo exibir uma mensagem adequada para explicar a situação.
Um aplicativo iOS nunca exibe uma opção de fechar ou sair. As pessoas param de usar um aplicativo quando mudam para outro aplicativo, retornam à tela 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 impede que seu aplicativo funcione como pretendido, você precisa contar aos usuários sobre a situação e explicar o que eles podem fazer a respeito.
Além do exposto, Bom, responda que eu só queria adicionar, pense em limpar sua memória.
Após a saída do seu aplicativo, o sistema operacional do iPhone limpará automaticamente qualquer coisa que seu aplicativo deixou para trás; portanto, liberar toda a memória manualmente pode aumentar a quantidade de tempo que seu aplicativo leva para sair.
HM, você pode 'ter que desistir do aplicativo se, digamos, seu aplicativo exigir uma conexão com a Internet. Você pode exibir um alerta e depois 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-quit (falha) o aplicativo sem fazer uma chamada de função de saída reveladora (0).
Por quê? Porque meu aplicativo usa o certificado fixando todas as chamadas da API de rede para evitar ataques de homem no meio. Isso inclui as chamadas de inicialização que meu aplicativo financeiro faz na inicialização.
Se a autenticação do certificado falhar, todo o meu erro de inicialização chama e deixa meu aplicativo em um estado indeterminado. Deixar o usuário voltar para casa e depois voltar ao aplicativo não ajuda, pois a menos que o aplicativo tenha sido eliminado pelo sistema operacional, ele ainda não é inicializado e não confiável.
Portanto, nesse caso, consideramos melhor colocar um alerta informando ao usuário que o aplicativo está operando em um ambiente inseguro e, quando eles atingem o "Fechar", a força desistiu do aplicativo usando o método mencionado acima.
[[UIApplication sharedApplication] terminateWithSuccess];
Funcionou bem e liga automaticamente
- (void)applicationWillTerminateUIApplication *)application delegate.
Para remover o aviso de tempo de compilação, adicione este código
@interface UIApplication(MyExtras)
- (void)terminateWithSuccess;
@end
O usuário deve decidir quando um aplicativo sai. Eu não acho que seja uma boa interação do usuário quando um aplicativo sai. Portanto, não há uma boa API para isso, apenas o botão home possui um.
Se houver um erro: implemente melhor ou notifique o usuário. Se tiver que haver uma reinicialização: implemente -o melhor para notificar o usuário.
Parece burro, mas é uma prática ruim sair do aplicativo sem deixar o usuário decidir e não notificá -lo. E como existe um botão doméstico para a interação do usuário, afirma a Apple, não deve haver duas coisas para a mesma função (saindo de um aplicativo).
Saia de um aplicativo de outra maneira que não o botão doméstico seja Realmente não-IIOS abordagem.
Eu fiz este ajudante, porém, que não usa coisas privadas:
void crash()
{ [[NSMutableArray new] addObject:NSStringFromClass(nil)]; }
Mas ainda não destinado à produção no meu caso. É para testar relatórios de falhas ou reiniciar rapidamente após uma redefinição de dados do núcleo. Apenas tornou seguro não ser rejeitado se a função deixada no código de produção.
Swift 4.2 (ou mais velho)
Biblioteca chamada Darvin
pode ser usado.
import Darwin
exit(0) // Here you go
NB: Isso não é recomendado nos aplicativos iOS.
Fazer isso fará com que seu log de falhas.
Você não deve chamar diretamente a função exit(0)
Como ele sairá do aplicativo imediatamente e parecerá que seu aplicativo está travado. É melhor mostrar aos usuários um alerta de confirmação e deixe -os fazer isso sozinhos.
Swift 4.2
func askForQuit(_ completion:@escaping (_ canQuit: Bool) -> Void) {
let alert = UIAlertController(title: "Confirmation!", message: "Do you want to quit the application", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.default, handler: { (action) in
alert.dismiss(animated: true, completion: nil)
completion(true)
}))
alert.addAction(UIAlertAction(title: "No", style: UIAlertAction.Style.cancel, handler: { (action) in
alert.dismiss(animated: true, completion: nil)
completion(false)
}))
self.present(alert, animated: true, completion: nil)
}
/// Will quit the application with animation
func quit() {
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
/// Sleep for a while to let the app goes in background
sleep(2)
exit(0)
}
Uso:
self.askForQuit { (canQuit) in
if canQuit {
self.quit()
}
}
Saia de um aplicativo de outra maneira
Eu fiz este ajudante, porém, que não usa coisas privadas:
Saída (0);
Pode ser apropriado sair de um aplicativo se for um aplicativo de vida longa que também é executado em segundo plano, por exemplo, para obter atualizações de localização (usando o Atualizações de localização capacidade de fundo para isso).
Por exemplo, digamos que o usuário faça login no seu aplicativo baseado em localização e empurre o aplicativo para o plano de fundo usando o botão doméstico. Nesse caso, seu aplicativo pode continuar funcionando, mas pode fazer sentido sair completamente. Seria bom para o usuário (libera memória e outros recursos que não precisam ser usados) e bom para a estabilidade do aplicativo (ou seja, certificando -se de que o aplicativo seja reiniciado periodicamente quando possível questões).
Isso poderia (embora provavelmente não deva, veja abaixo :-) ser alcançado com algo como:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if (/* logged out */) {
exit(0);
} else {
// normal handling.
}
}
Já que o aplicativo sairia fora do fundo Não parecerá errado para o usuário e não se parecerá com uma falha, desde que a interface do usuário seja restaurada na próxima vez que executar o aplicativo. Em outras palavras, para o usuário, não seria diferente de uma terminação iniciada pelo sistema do aplicativo quando o aplicativo estiver em segundo plano.
Ainda assim, seria preferível usar uma abordagem mais padrão para informar o sistema que o aplicativo pode ser encerrado. Por exemplo, neste caso, certificando -se de que o GPS não esteja em uso, parando de solicitar atualizações de localização, incluindo desativar o Localização atual em uma visualização do mapa, se presente. Dessa forma, o sistema cuidará de encerrar o aplicativo alguns minutos (ou seja, [[UIApplication sharedApplication] backgroundTimeRemaining]
) Depois que o aplicativo entra no plano de fundo. Isso obteria os mesmos benefícios sem precisar 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, usando exit(0)
nunca seria apropriado para o aplicativo de produção média que é executado em primeiro plano, conforme outras respostas que referenciam http://developer.apple.com/iphone/library/qa/qa2008/qa1561.html