Active — o estado ativo do ciclo de vida de uma aplicação iOS, no qual ela está em primeiro plano, recebe eventos de toque e interage com o usuário. Vamos descobrir como o estado Active funciona, quais métodos do UIApplicationDelegate são responsáveis por ele e como lidar corretamente com as transições entre Active e Inactive no Swift.
Pontos principais
Active — um estado do ciclo de vida da aplicação móvel no qual ela está em primeiro plano, exibida na tela do dispositivo e interage ativamente com o usuário. Neste estado, a aplicação recebe todos os eventos de toque, pressionamentos de teclas, dados do acelerômetro e giroscópio, e tem acesso completo ao processador gráfico para renderizar a interface.
No iOS, o estado Active faz parte do modelo de ciclo de vida de cinco estados: Not Running → Inactive → Active → Inactive → Background → Suspended → Not Running. No Android, o equivalente é o estado da Activity após a chamada onResume, quando a Activity está no topo da pilha e aceita entrada do usuário. Active é o único estado em que a UI é totalmente interativa e responde a gestos, rolagem, toques e animações.
O sistema concede a uma aplicação em Active a máxima prioridade de CPU e RAM. Isso significa que o sistema não finalizará tal aplicação quando os recursos estiverem escassos — os processos em segundo plano e suspensos serão descarregados primeiro. No entanto, a aplicação deve usar os recursos de forma eficiente para evitar esgotar a bateria e causar limitação da CPU.
Para o usuário, Active é o estado normal de trabalho com uma aplicação. O usuário vê a interface, pode pressionar botões, preencher formulários e percorrer os feeds. Qualquer interrupção deste estado (uma chamada, notificação, deslizar para cima para o Control Center) move a aplicação para Inactive, após o que ela pode retornar ao Active ou ir para Background.
O iOS usa UIApplicationMain para gerenciar o estado. Ao fazer a transição para Active, o sistema chama applicationDidBecomeActive. Para SwiftUI, o mecanismo equivalente é observar scenePhase através do Environment. O Android usa onResume como indicador de que a Activity está em primeiro plano. Ambas as abordagens garantem que a aplicação receba uma notificação de mudança de estado e possa adaptar seu comportamento.
| Plataforma | Método/Evento | Swift (UIKit) | SwiftUI | Android (Kotlin) |
|---|---|---|---|---|
| iOS | Transição para Active | applicationDidBecomeActive | scenePhase == .active | — |
| iOS | Saída de Active | applicationWillResignActive | scenePhase == .inactive | — |
| Android | Transição para Active | — | — | onResume() |
| Android | Saída de Active | — | — | onPause() |
No iOS, o estado Active é gerenciado através do UIApplicationDelegate. O método principal é applicationDidBecomeActive(_:). Ele é chamado no primeiro lançamento da aplicação e ao retornar do Inactive. Este método é o local ideal para retomar tarefas que foram pausadas ao entrar em Inactive: iniciar animações, retomar temporizadores, reiniciar sensores, verificar atualizações de dados no servidor.
Com o iOS 13, a Apple introduziu o UISceneDelegate para suportar múltiplas janelas no iPad. Neste caso, applicationDidBecomeActive é substituído por sceneDidBecomeActive para cada cena individual. Aplicações que suportam apenas uma única tela podem continuar usando UIApplicationDelegate. Ambas as abordagens são chamadas quando a aplicação ou cena se torna ativa.
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// Aplicação tornou-se ativa — retomando tarefas
func applicationDidBecomeActive(_ application: UIApplication) {
resumeAnimations()
restartTimers()
refreshDataIfNeeded()
startObservingSensors()
}
// Aplicação está perdendo atividade — pausando
func applicationWillResignActive(_ application: UIApplication) {
pauseAnimations()
stopTimers()
saveDraftData()
}
private func resumeAnimations() {
UIView.animate(withDuration: 0.3) {
// Retomando animações da UI
}
}
private func refreshDataIfNeeded() {
let lastRefresh = UserDefaults.standard.object(forKey: "lastRefresh") as? Date ?? .distantPast
if Date().timeIntervalSince(lastRefresh) > 300 {
fetchDataFromServer()
}
}
}O código mostra o tratamento correto de Active no UIKit. applicationDidBecomeActive retoma animações, temporizadores e verifica se são necessárias atualizações de dados. applicationWillResignActive pausa tudo que poderia consumir recursos e salva rascunhos. Esse par de métodos garante que a aplicação responda corretamente às mudanças de estado.
SwiftUI não tem AppDelegate — o gerenciamento de estado ocorre através de Environment<ScenePhase>. O valor .active é definido quando a cena está em primeiro plano e interativa. SwiftUI reinicia automaticamente as animações e atualizações ao retornar ao Active. O desenvolvedor só precisa se inscrever no onChange para realizar efeitos colaterais.
import SwiftUI
@main
struct ActiveDemoApp: App {
@Environment(\.scenePhase) private var scenePhase
var body: some Scene {
WindowGroup {
ContentView()
}
.onChange(of: scenePhase) { oldPhase, newPhase in
switch newPhase {
case .active:
print("Cena tornou-se ativa")
resumeWork()
case .inactive:
print("Cena tornou-se inativa")
pauseWork()
case .background:
print("Cena foi para o fundo")
saveState()
@unknown default:
break
}
}
}
private func resumeWork() {
// Retomando requisições de rede, animações
}
private func pauseWork() {
// Pausando tarefas sensíveis ao tempo
}
private func saveState() {
// Salvando estado da aplicação
}
}No SwiftUI, scenePhase é a única fonte da verdade sobre o estado da aplicação. onChange permite realizar ações em cada transição. É importante lembrar que scenePhase está disponível apenas no iOS 14+ e no SwiftUI Lifecycle. Para aplicações UIKit com telas SwiftUI, use a abordagem UIApplicationDelegate.
Active pode ser alcançado através de vários caminhos. O primeiro e mais óbvio é uma inicialização a frio: o usuário toca no ícone, a aplicação vai de Not Running através de Inactive para Active. O segundo é retornar do fundo: o usuário volta para a aplicação através do App Switcher, a aplicação passa por Inactive e se torna Active. O terceiro é retornar de uma interrupção temporária: o usuário termina uma chamada, fecha o Control Center ou responde a uma notificação — a aplicação retorna de Inactive para Active.
Not Running → Inactive → Active — inicialização a frio. Background → Inactive → Active — retorno do fundo. Inactive → Active — retorno de uma interrupção temporária. Em cada caso, applicationDidBecomeActive é chamado, mas o contexto pode diferir. Numa inicialização a frio, didFinishLaunchingWithOptions é chamado antes de Active; ao retornar do fundo, willEnterForeground é chamado. O desenvolvedor pode usar essas diferenças para escolher uma estratégia de restauração de estado.
| Cenário | Caminho de transição | Callbacks iOS | Callbacks Android |
|---|---|---|---|
| Inicialização a frio | Not Running → Active | didFinishLaunching → didBecomeActive | onCreate → onStart → onResume |
| Retorno do fundo | Background → Active | willEnterForeground → didBecomeActive | onRestart → onStart → onResume |
| Retorno de Suspended | Suspended → Active | willEnterForeground → didBecomeActive | onRestart → onStart → onResume |
| Após interrupção | Inactive → Active | didBecomeActive | onResume |
Nota importante: ao retornar de Suspended, o iOS não chama didFinishLaunchingWithOptions porque a aplicação já estava carregada na memória. Isso significa que o código de inicialização colocado neste método não é reexecutado. Os desenvolvedores frequentemente esquecem disso e transferem a lógica crítica para applicationWillEnterForeground ou applicationDidBecomeActive para ambos os cenários.
No Android, o equivalente de Active é o estado da Activity após a chamada onResume(). Uma Activity é considerada ativa quando está em primeiro plano e aceita entrada do usuário. Este estado corresponde ao topo da pilha de Activities. Se outra Activity aparecer por cima (mesmo parcialmente), a Activity atual transita para o estado onPause — o equivalente ao Inactive do iOS.
Uma diferença chave no Android é que múltiplas Activities podem estar ativas simultaneamente no modo multi-janela (split screen, freeform). Neste caso, a Activity com a qual o usuário está interagindo é considerada ativa, enquanto a vizinha está pausada (onPause). O iOS não suporta multi-janela no iPhone, apenas no iPad através de UIScene.
class MainActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
// Aplicação tornou-se ativa — retomando tarefas
resumeCameraPreview()
startLocationUpdates()
activateSensors()
}
override fun onPause() {
super.onPause()
// Aplicação está perdendo atividade — liberando recursos
releaseCamera()
stopLocationUpdates()
deactivateSensors()
}
private fun resumeCameraPreview() {
// Iniciando pré-visualização da câmera (requer permissão)
cameraProvider?.unbindAll()
cameraProvider?.bindToLifecycle(
this,
cameraSelector,
preview,
imageAnalyzer
)
}
private fun startLocationUpdates() {
val locationRequest = LocationRequest.Builder(
Priority.PRIORITY_HIGH_ACCURACY, 5000
).build()
locationClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
}O código mostra o tratamento de Active no Android através de onResume/onPause. onResume retoma a câmera, geolocalização e sensores — recursos que só devem estar ativos quando a aplicação está visível para o usuário. onPause libera esses recursos para evitar esgotar a bateria. A API CameraX lifecycle-aware pausa automaticamente a pré-visualização no onPause.
Primeira regra — não realize operações pesadas em applicationDidBecomeActive ou onResume. Carregamento de dados, análise JSON, trabalho com banco de dados — tudo isso deve ser assíncrono e não bloquear a thread principal. Use GCD (DispatchQueue) no iOS e Coroutines no Kotlin para tarefas em segundo plano. A thread principal deve apenas atualizar a UI e iniciar operações assíncronas.
Segunda regra — sincronize o estado a cada retorno ao Active. O usuário pode ter alterado configurações numa aplicação do sistema, recebido uma notificação push ou atualizado dados noutra aplicação. Verifique a relevância do cache ao fazer a transição para Active — os dados podem ter ficado obsoletos enquanto o usuário estava ausente.
Terceira regra — não confie no Active como o único estado. A aplicação pode saltar Active e ir diretamente de Not Running para Background (se for iniciada em modo fundo). No iOS, isso ocorre quando iniciada através de uma notificação push com a opção content-available. No Android, quando iniciada através de BroadcastReceiver. Verifique sempre o estado atual antes de realizar operações de UI.
Quarta regra — use Activity Result API no Android em vez de onActivityResult. Isso permite lidar com o resultado de chamadas de câmera, galeria ou permissões diretamente no estado Active sem perda de dados na recriação da Activity. Para iOS, use async/await com UIApplication.shared.open para diálogos do sistema.
import UIKit
final class ActiveStateManager {
static let shared = ActiveStateManager()
private var isActive = false
func setActive(_ active: Bool) {
isActive = active
if active {
NotificationCenter.default.post(name: .appDidBecomeActive, object: nil)
}
}
func performWhenActive(_ block: @escaping () -> Void) {
if isActive {
block()
} else {
// Adiar execução até retornar ao Active
NotificationCenter.default.addObserver(
forName: .appDidBecomeActive,
object: nil,
queue: .main
) { _ in
block()
}
}
}
}
extension Notification.Name {
static let appDidBecomeActive = Notification.Name("appDidBecomeActive")
}O código mostra um gerenciador de estado Active que permite a outros componentes da aplicação verificar o estado ativo atual. performWhenActive executa o bloco imediatamente se a aplicação estiver ativa, ou adia a execução até retornar ao Active. Isso é útil para serviços que precisam realizar uma ação após o usuário retornar à aplicação.
Perguntas Frequentes
O método é chamado sempre que a aplicação transita para o estado ativo: no primeiro lançamento, ao retornar do fundo, após fechar o Control Center ou Notification Center, após terminar uma chamada. Numa sessão normal pode ser chamado 5–10 vezes dependendo das ações do usuário. Não coloque inicialização única neste método.
Visible é um termo não oficial que significa que a aplicação está visível no ecrã mas pode não receber eventos (por exemplo, parcialmente coberta por outra janela no iPad). Active é o estado oficial no qual a aplicação é tanto visível como interativa. No iPhone, uma aplicação Visible é sempre Active; no iPad, é possível uma situação Visible + Inactive.
willEnterForeground é chamado ao retornar do fundo, mas a aplicação ainda não está ativa — está em Inactive. didBecomeActive é chamado depois que a aplicação se torna totalmente interativa. Se precisar realizar uma ação antes do usuário ver a interface — use willEnterForeground. Se depois de exibir — use didBecomeActive.
Não. Active implica que a aplicação está em primeiro plano e exibida no ecrã. Sem uma UI visível, a aplicação pode estar em Background ou Suspended. A exceção é o modo multi-janela do iPad, onde uma janela pode estar ativa e outra não, mas ambas estão visíveis. VoiceOver e gravador de voz não alteram esta regra.
No simulador iOS, prima Cmd+Shift+H para ir ao ecrã inicial (a aplicação vai para Background), depois toque novamente no ícone da aplicação. Use Cmd+L para bloquear o ecrã (willResignActive) e desbloquear (didBecomeActive). Para testar Inactive, abra o Control Center (Cmd+Shift+; para teclado macOS) ou Notification Center.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também