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?

Foi útil?

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ÇÕES exit 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 semelhante UIApplicationDelegate 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, ou assert 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:

  1. Ligue manualmente para o - (void)applicationWillTerminate:(UIApplication *)application no delegado.
  2. 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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top