Ciclo de vida com appDelegate em Swift: um guia para iniciantes

Felipe Bandeira
Apple Developer Academy | UFPE
9 min readJun 23, 2020

--

Talvez você, como eu, tenha tido dificuldades para entender como funciona o ciclo de vida de um app em Swift. Pra quem não está acostumado, entender como tudo se encaixa é, sim, difícil. Pois foi sabendo disso, e querendo ajudar você a entender direitinho como tudo funciona do começo ao fim, que resolvi escrever este pequeno guia :)

É importante salientar que, nesse texto, não falarei sobre o SceneDelegate. Tudo será feito com o appDelegate, ok?

Afinal, o que é o appDelegate?

Dizia John Beckley: a maioria das pessoas não planeja fracassar, mas fracassa por não planejar. Na construção de apps, isso não é diferente. A menos que você queira cair no vale do esquecimento, é importante planejar como o seu app vai funcionar do começo ao fim.

Quem ajuda nesse planejamento é o protocolo UIApplicationDelegate. Ele é como uma lista que serve pra lembrar você de grandes eventos que costumam acontecer durante o ciclo de vida de um app (o app ser aberto, ser deixado de lado por outro app, ser fechado etc). Para cada evento, temos um método específico, que personalizamos de acordo com o que queremos que aconteça no nosso app.

O AppDelegate é um objeto que contém todas as “respostas” para os métodos do protocolo UIApplicationDelegate. Ele diz ao seu app o que deve ser feito em cada uma daquelas ocasiões (por exemplo: quando for inicializado, o app deve puxar informações da nuvem ou abrir só com o que tem no celular? Se for colocado em background, deve salvar alguma informação ou só pausar a música que estava tocando?).

AppDelegate dentro dos arquivos do projeto no Xcode

Você pode encontrar o appDelegate dentro dos arquivos do seu projeto no Xcode, e todas as funções que falaremos a seguir estão lá dentro! E agora que você sabe disso, vamos ao que realmente importa.

O começo da vida de um app

Para entender como um ciclo de vida funciona "na prática", vamos pensar em um app como… o Instagram. A primeira interação de qualquer usuário com ele acontece na tela de início, concorda? Até então, nada estava acontecendo, mas basta um clique no ícone para a magia do código entrar em ação. Bum! A tela com a logo do app aparece e, num piscar de olhos, já estamos no nosso feed.

Ilustração da Apple com os diferentes estados do ciclo de vida

Pode não parecer, mas algumas coisas muito importantes aconteceram nesse pequeno intervalo de tempo. Primeiramente, o app passou por três estados diferentes do ciclo de vida. Ele começou sem estar rodando, passou por um carregamento rápido e entrou em pleno funcionamento logo em seguida, como vemos na parte de cima dessa figura.

Sabe aquela tela rápida que aparece com a logo do app? Ela é característica do estado inativo, que não dura mais que alguns segundos, mas é extremamente importante. É nesse estado que o app carrega grande parte das suas informações, fazendo com que seu feed apareça bonitinho logo depois.

Uma vez que o feed é mostrado, entramos oficialmente no estado ativo. Aqui, seu app está a pleno vapor, pronto para receber todas as interações possíveis e imagináveis. Mas esse processo de inicialização, que leva o usuário da tela principal do iPhone ao feed do app, não acontece sozinho!

Durante a inicialização, quais as funções do AppDelegate que entram em ação e o que elas fazem?

Em geral, duas funções do AppDelegate são ativadas durante a inicialização: primeiro, a willFinishLaunchingWIthOptions, e depois, a didFinishLaunchingWithOptions, que estão na imagem abaixo.

Métodos do appDelegate presentes na inicialização

A primeira é chamada assim que a inicialização começa. Em geral, ela é utilizada para preparar dados e informações que serão necessárias ao app. No Instagram, por exemplo, isso significaria checar se você recebeu algum direct, ver se alguém comentou na sua foto…

O UIKit, então, chama a segunda função, ao final da inicialização. A essa altura, seu app já deve ter as informações todas que precisa. É hora de juntar elas e preparar o que o app fará em seguida, como construir e organizar a tela principal com o seu feed!

Quando você vê o app na tela, dizemos que ele está em foreground. Quase todo o potencial do seu iPhone está sendo dedicado a rodar esse único app, para que você tenha o melhor desempenho possível. Mas sabemos que a vida não é perfeita, distrações existem, e às vezes nós temos que tirar aquele app da tela principal. Quando isso acontece, dizemos que o app foi para o background.

O que faz com que um app entre em background?

Apps podem rodar em background por diversas razões. Pode ser que, depois de jogar um jogo, o usuário simplesmente queira ver mensagens e mude de app. Ou pode ser que, no meio da noite, o app de emails precise atualizar para ver se não chegou nada. Seja como for, o background é uma etapa de transição entre o estado ativo e o estado suspenso.

Resumindo, o background é parecido com o estado inativo. A diferença é o momento em que acontece. A primeira possibilidade é quando você alterna entre aplicativos, como sair do Instagram para ir, digamos, ao WhatsApp. Assim que você sai, o Instagram entra em modo de background, onde passa pouquíssimo tempo, antes de ir para o estado suspenso. É no background que ele salva as últimas coisas que precisa e desativa tudo que estava acontecendo (afinal de contas, o ideal é que seu app use pouca memória, ou mesmo nenhuma, quando não estiver em foreground!).

A segunda possibilidade acontece quando o seu iPhone verifica se alguma mensagem chegou no meio da noite. O app, que estava suspenso, entra rápido em background para executar uma tarefa e, em seguida, volta para o modo suspenso.

Agora que você entende as duas situações, vamos para a parte técnica da coisa.

O que REALMENTE acontece com um app quando ele está saindo do estado ativo para o background?

Peguemos a primeira possibilidade que falamos acima, em que o usuário resolve deixar de rolar o feed para ver mensagens instantâneas. Assim que sai do foreground, o sistema realiza um processo (chamado de desativação do app) imediatamente antes de levá-lo para o background. Isso também ocorre quando o app sofre uma interrupção, como uma ligação.

Durante a desativação, o primeiro método a ser chamado é o applicationWillResignActive. Ele é responsável por fazer imediatamente tudo que é mais importante: salvar dados, pausar o gameplay, interromper timers etc. Uma vez que tudo que é essencial já foi resolvido, o app entra em background, e a prioridade agora se torna liberar memória e usar o mínimo possível (se puder, até, não usar nada). Quem cuida disso é o applicationDidEnterBackground. Em geral, esse método descarta imagens e outros conteúdos que podem ser recarregados depois, esconde senhas que foram inseridas, fecha conexões que estavam em aberto, desconecta a câmera ou outros recursos que estavam em uso…

Métodos que entram em ação quando o app está indo para o background

Uma curiosidade interessante é que, depois de fazer tudo isso, o sistema tira um print da view que estava aberta da última vez que o usuário usou o app, e deixa esse print exposto no switcher de apps (aquele menu que você vê todos os apps que “estão abertos”). Isso é feito ao final do processo para evitar que senhas e informações sensíveis fiquem expostas nos prints!

Para entender mais sobre apps que possuem funções que funcionam em background, como atualizar mensagens, vale a pena checar o final desse manual.

E o que acontece quando um app volta do background para o foreground?

Pois bem! Vamos supor que usuário saiu do Instagram, viu o WhatsApp como queria, passou algum tempo conversando e, depois, quis voltar ao Instagram novamente. Por trás das câmeras, o processo que acontece aqui é muito similar ao de inicialização, que falamos lá em cima. Os métodos utilizados é que variam um pouco.

Aqui, entra em ação o applicationWillEnterForeground. Pra que ele serve? Pra fazer o mesmo que o willFinishLaunchingWithOptions faz! checar se você recebeu algum direct, ver se alguém comentou na sua foto…

A diferença é que o applicationWillEnterForeground é chamado somente quando o app está em background e vai voltar à ativa. Por outro lado, o willFinishLaunchingWIthOptions é chamado quando o app é aberto do zero. São caminhos diferentes que levam à preparação dos dados do app para a ativação!

E, se quando estamos abrindo o app do zero, o didFinishLaunchingWithOptions é quem organiza o que irá ser exibido na tela, quem faz isso quando ele está voltando do background é o applicationDidBecomeActive. Seja carregar uma nova tela, exibir controles de um jogo pausado, fazer timers voltarem a rodar… Todas essas coisas ficam a cargo desse método.

Métodos que auxiliam o app no retorno do background para o foreground

(Ele inclusive avisa aos view controllers que suas views estão prestes a serem exibidas. Por isso, alguns métodos próprios de view controller, como o viewWillAppear, podem ser ativados quando o applicationDidBecomeActive retorna. Isso faz com que animações voltem a se mexer, músicas voltem a tocar e por aí vai).

Vale salientar que o applicationDidBecomeActive e o applicationWillEnterForeground são chamados OBRIGATORIAMENTE em sequência.

Existe alguma hora que o app é fechado pra valer?

Existe, e há um método específico para isso. Sabe quando, no app switcher, você desliza um app para cima e fecha ele de vez? Pois é. Quando o applicationWillTerminate é chamado, pode ter certeza que o negócio é sério.

Mais sinistro que ao applicationWillTerminate, nem o próprio Terminator

Esse método é reservado para fazer as últimas ações do app (salvar dados importantes, liberar recursos que estavam sendo compartilhados etc) e fazer a limpeza final na memória. E tem mais: se esse método não retornar em cinco segundos (literalmente), o sistema fecha ele junto. É brutal, mesmo…

Recapitulando…

Existem cinco possíveis estados no ciclo de vida de um app:

  • Desligado: dispensa maiores explicações
  • Inativo: estado de transição onde ocorrem carregamentos rápidos
  • Ativo: estado principal, onde o usuário interage com o app
  • Background: estado de transição, onde são realizadas atividades rápidas antes de o app ser reativado ou suspenso
  • Suspenso: app quase não executa tarefas e quase não consome memória

E, dentro desses estados, existem sete métodos que devemos considerar:

  • willFinishLaunchingWithOptions: acontece no estado inativo para carregar dados, principalmente
  • didFinishLaunchingWithOptions: acontece no estado inativo para carregar as partes do app que serão exibidas na tela, a seguir
  • applicationWillResignActive: acontece no estado ativo, quando o app é avisado que não vai mais ser utilizado e precisa salvar imediatamente dados e informações relevantes
  • applicationDidEnterBackground: acontece já no background, para terminar o processo de limpeza e reduzir o consumo de memória
  • applicationWillEnterForeground: acontece no background para carregar dados, principalmente
  • applicationDidBecomeActive: acontece no background para carregar as partes do app que serão exibidas na tela, a seguir
  • applicationWillTerminate: acontece quando o usuário fecha o app de vez, esteja ele ativo ou suspenso, para limpar tudo e liberar a memória

Por fim, um conselho: por que devemos nos preocupar em preservar a UI ao longo das reinicializações?

Por vezes, quando o app está em background, o sistema fecha ele para liberar espaço para outras aplicações. O usuário, no entanto, não sabe que o app foi fechado, e espera que, ao reabrir a janela do app, tudo esteja exatamente como antes! Para que isso ocorra, configurar-lo para preservar e restaurar a UI é importante. A Apple ensina como fazer isso nesse manual.

That's all, folks!

Espero que, depois desta leitura, você consiga compreender melhor quais são as etapas do ciclo de vida de um app e as funções presentes em cada uma. Até a próxima :D

--

--

Felipe Bandeira
Apple Developer Academy | UFPE

Passionate by exploring things and sharing knowledge. Currently focusing on ML/AI but always up for learning new things