Active — el estado activo del ciclo de vida de una aplicación iOS, en el que se encuentra en primer plano, recibe eventos táctiles e interactúa con el usuario. Analicemos cómo funciona el estado Active, qué métodos de UIApplicationDelegate son responsables de él y cómo manejar correctamente las transiciones entre Active e Inactive en Swift.
Puntos clave
Active — un estado del ciclo de vida de la aplicación móvil en el que se encuentra en primer plano, se muestra en la pantalla del dispositivo e interactúa activamente con el usuario. En este estado, la aplicación recibe todos los eventos táctiles, pulsaciones de teclas, datos del acelerómetro y giróscopo, y tiene acceso completo al procesador gráfico para renderizar la interfaz.
En iOS, el estado Active es parte del modelo de ciclo de vida de cinco estados: Not Running → Inactive → Active → Inactive → Background → Suspended → Not Running. En Android, el equivalente es el estado de Activity después de llamar a onResume, cuando la Activity está en la parte superior de la pila y acepta entrada del usuario. Active es el único estado en el que la UI es completamente interactiva y responde a gestos, desplazamiento, toques y animaciones.
El sistema otorga a una aplicación en Active la máxima prioridad de CPU y RAM. Esto significa que el sistema no finalizará dicha aplicación cuando los recursos sean escasos — los procesos en segundo plano y suspendidos se descargarán primero. Sin embargo, la aplicación debe usar los recursos de manera eficiente para evitar agotar la batería y provocar la limitación de la CPU.
Para el usuario, Active es el estado normal de trabajo con una aplicación. El usuario ve la interfaz, puede presionar botones, llenar formularios y desplazarse por los feeds. Cualquier interrupción de este estado (una llamada, notificación, deslizar hacia arriba para Control Center) mueve la aplicación a Inactive, después de lo cual puede volver a Active o ir a Background.
iOS usa UIApplicationMain para gestionar el estado. Al hacer la transición a Active, el sistema llama a applicationDidBecomeActive. Para SwiftUI, el mecanismo equivalente es observar scenePhase a través de Environment. Android usa onResume como indicador de que la Activity está en primer plano. Ambos enfoques garantizan que la aplicación reciba una notificación de cambio de estado y pueda adaptar su comportamiento.
| Plataforma | Método/Evento | Swift (UIKit) | SwiftUI | Android (Kotlin) |
|---|---|---|---|---|
| iOS | Transición a Active | applicationDidBecomeActive | scenePhase == .active | — |
| iOS | Salida de Active | applicationWillResignActive | scenePhase == .inactive | — |
| Android | Transición a Active | — | — | onResume() |
| Android | Salida de Active | — | — | onPause() |
En iOS, el estado Active se maneja a través de UIApplicationDelegate. El método principal es applicationDidBecomeActive(_:). Se llama en el primer inicio de la aplicación y al regresar de Inactive. Este método es el lugar ideal para reanudar tareas que se pausaron al entrar en Inactive: iniciar animaciones, reanudar temporizadores, reiniciar sensores, verificar actualizaciones de datos en el servidor.
Con iOS 13, Apple presentó UISceneDelegate para admitir múltiples ventanas en iPad. En este caso, applicationDidBecomeActive se reemplaza por sceneDidBecomeActive para cada escena individual. Las aplicaciones que solo admiten una pantalla pueden continuar usando UIApplicationDelegate. Ambos enfoques se llaman cuando la aplicación o escena se vuelve activa.
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// La aplicación se volvió activa — reanudando tareas
func applicationDidBecomeActive(_ application: UIApplication) {
resumeAnimations()
restartTimers()
refreshDataIfNeeded()
startObservingSensors()
}
// La aplicación está perdiendo actividad — pausando
func applicationWillResignActive(_ application: UIApplication) {
pauseAnimations()
stopTimers()
saveDraftData()
}
private func resumeAnimations() {
UIView.animate(withDuration: 0.3) {
// Reanudando animaciones de UI
}
}
private func refreshDataIfNeeded() {
let lastRefresh = UserDefaults.standard.object(forKey: "lastRefresh") as? Date ?? .distantPast
if Date().timeIntervalSince(lastRefresh) > 300 {
fetchDataFromServer()
}
}
}El código muestra el manejo correcto de Active en UIKit. applicationDidBecomeActive reanuda animaciones, temporizadores y verifica si se requieren actualizaciones de datos. applicationWillResignActive pausa todo lo que podría consumir recursos y guarda borradores. Este par de métodos garantiza que la aplicación responda correctamente a los cambios de estado.
SwiftUI no tiene AppDelegate — la gestión del estado ocurre a través de Environment<ScenePhase>. El valor .active se establece cuando la escena está en primer plano e interactiva. SwiftUI reinicia automáticamente las animaciones y actualizaciones al regresar a Active. El desarrollador solo necesita suscribirse a onChange para realizar efectos secundarios.
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("La escena se volvió activa")
resumeWork()
case .inactive:
print("La escena se volvió inactiva")
pauseWork()
case .background:
print("La escena fue al fondo")
saveState()
@unknown default:
break
}
}
}
private func resumeWork() {
// Reanudando solicitudes de red, animaciones
}
private func pauseWork() {
// Pausando tareas sensibles al tiempo
}
private func saveState() {
// Guardando el estado de la aplicación
}
}En SwiftUI, scenePhase es la única fuente de verdad sobre el estado de la aplicación. onChange permite realizar acciones en cada transición. Es importante recordar que scenePhase solo está disponible en iOS 14+ y en el SwiftUI Lifecycle. Para aplicaciones UIKit con pantallas SwiftUI, use el enfoque UIApplicationDelegate.
Active se puede alcanzar a través de varios caminos. El primero y más obvio es un inicio en frío: el usuario toca el ícono, la aplicación pasa de Not Running a través de Inactive a Active. El segundo es regresar del fondo: el usuario vuelve a la aplicación a través del App Switcher, la aplicación pasa por Inactive y se vuelve Active. El tercero es regresar de una interrupción temporal: el usuario finaliza una llamada, cierra Control Center o responde a una notificación — la aplicación regresa de Inactive a Active.
Not Running → Inactive → Active — inicio en frío. Background → Inactive → Active — regreso del fondo. Inactive → Active — regreso de una interrupción temporal. En cada caso se llama a applicationDidBecomeActive, pero el contexto puede diferir. En un inicio en frío, se llama a didFinishLaunchingWithOptions antes de Active; al regresar del fondo, se llama a willEnterForeground. El desarrollador puede usar estas diferencias para elegir una estrategia de restauración del estado.
| Escenario | Ruta de transición | Callbacks iOS | Callbacks Android |
|---|---|---|---|
| Inicio en frío | Not Running → Active | didFinishLaunching → didBecomeActive | onCreate → onStart → onResume |
| Regreso del fondo | Background → Active | willEnterForeground → didBecomeActive | onRestart → onStart → onResume |
| Regreso de Suspended | Suspended → Active | willEnterForeground → didBecomeActive | onRestart → onStart → onResume |
| Después de interrupción | Inactive → Active | didBecomeActive | onResume |
Nota importante: al regresar de Suspended, iOS no llama a didFinishLaunchingWithOptions porque la aplicación ya estaba cargada en memoria. Esto significa que el código de inicialización colocado en este método no se vuelve a ejecutar. Los desarrolladores a menudo olvidan esto y trasladan la lógica crítica a applicationWillEnterForeground o applicationDidBecomeActive para ambos escenarios.
En Android, el equivalente de Active es el estado de Activity después de llamar a onResume(). Una Activity se considera activa cuando está en primer plano y acepta entrada del usuario. Este estado corresponde a la parte superior de la pila de Activities. Si otra Activity aparece encima (incluso parcialmente), la Activity actual pasa al estado onPause — el equivalente de Inactive en iOS.
Una diferencia clave en Android es que múltiples Activities pueden estar activas simultáneamente en modo multi-ventana (split screen, freeform). En este caso, la Activity con la que el usuario interactúa se considera activa, mientras que la vecina está en pausa (onPause). iOS no admite multi-ventana en iPhone, solo en iPad a través de UIScene.
class MainActivity : AppCompatActivity() {
override fun onResume() {
super.onResume()
// La aplicación se volvió activa — reanudando tareas
resumeCameraPreview()
startLocationUpdates()
activateSensors()
}
override fun onPause() {
super.onPause()
// La aplicación está perdiendo actividad — liberando recursos
releaseCamera()
stopLocationUpdates()
deactivateSensors()
}
private fun resumeCameraPreview() {
// Iniciando vista previa de la cámara (requiere permiso)
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()
)
}
}El código muestra el manejo de Active en Android a través de onResume/onPause. onResume reanuda la cámara, la geolocalización y los sensores — recursos que solo deben estar activos cuando la aplicación es visible para el usuario. onPause libera estos recursos para evitar agotar la batería. La API CameraX lifecycle-aware pausa automáticamente la vista previa en onPause.
Primera regla — no realice operaciones pesadas en applicationDidBecomeActive u onResume. Carga de datos, análisis JSON, trabajo con base de datos — todo esto debe ser asíncrono y no bloquear el hilo principal. Use GCD (DispatchQueue) en iOS y Coroutines en Kotlin para tareas en segundo plano. El hilo principal solo debe actualizar la UI e iniciar operaciones asíncronas.
Segunda regla — sincronice el estado en cada regreso a Active. El usuario podría haber cambiado la configuración en una aplicación del sistema, recibido una notificación push o actualizado datos en otra aplicación. Verifique la relevancia de la caché al hacer la transición a Active — los datos podrían haber quedado obsoletos mientras el usuario estaba ausente.
Tercera regla — no confíe en Active como el único estado. La aplicación puede saltarse Active e ir directamente de Not Running a Background (si se inicia en modo fondo). En iOS, esto ocurre cuando se inicia a través de una notificación push con la opción content-available. En Android, cuando se inicia a través de BroadcastReceiver. Siempre verifique el estado actual antes de realizar operaciones de UI.
Cuarta regla — use Activity Result API en Android en lugar de onActivityResult. Esto permite manejar el resultado de llamadas a la cámara, galería o permisos directamente en el estado Active sin pérdida de datos al recrear la Activity. Para iOS, use async/await con UIApplication.shared.open para diálogos del 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 {
// Diferir la ejecución hasta regresar a Active
NotificationCenter.default.addObserver(
forName: .appDidBecomeActive,
object: nil,
queue: .main
) { _ in
block()
}
}
}
}
extension Notification.Name {
static let appDidBecomeActive = Notification.Name("appDidBecomeActive")
}El código muestra un administrador de estado Active que permite a otros componentes de la aplicación verificar el estado activo actual. performWhenActive ejecuta el bloque inmediatamente si la aplicación está activa, o pospone la ejecución hasta regresar a Active. Esto es útil para servicios que necesitan realizar una acción después de que el usuario regrese a la aplicación.
Preguntas frecuentes
El método se llama cada vez que la aplicación transiciona al estado activo: en el primer inicio, al regresar del fondo, después de cerrar Control Center o Notification Center, después de finalizar una llamada. En una sesión normal puede llamarse 5–10 veces dependiendo de las acciones del usuario. No coloque inicializaciones únicas en este método.
Visible es un término no oficial que significa que la aplicación es visible en la pantalla pero puede no recibir eventos (por ejemplo, parcialmente cubierta por otra ventana en iPad). Active es el estado oficial en el que la aplicación es tanto visible como interactiva. En iPhone, una aplicación Visible siempre es Active; en iPad, es posible una situación Visible + Inactive.
willEnterForeground se llama al regresar del fondo, pero la aplicación aún no está activa — está en Inactive. didBecomeActive se llama después de que la aplicación se vuelve completamente interactiva. Si necesita realizar una acción antes de que el usuario vea la interfaz — use willEnterForeground. Si después de mostrarla — use didBecomeActive.
No. Active implica que la aplicación está en primer plano y se muestra en la pantalla. Sin una UI visible, la aplicación puede estar en Background o Suspended. La excepción es el modo multi-ventana de iPad, donde una ventana puede estar activa y otra no, pero ambas son visibles. VoiceOver y la grabadora de voz no cambian esta regla.
En el simulador de iOS, presione Cmd+Shift+H para ir a la pantalla de inicio (la aplicación va a Background), luego toque el icono de la aplicación nuevamente. Use Cmd+L para bloquear la pantalla (willResignActive) y desbloquear (didBecomeActive). Para probar Inactive, abra Control Center (Cmd+Shift+; para teclado macOS) o Notification Center.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también