Suspended — qué es, congelación de la aplicación en segundo plano en iOS

Autor: IT Sectr Publicado: 2026-03-03 Tiempo de lectura: 11 min

Suspended — un estado pausado del ciclo de vida de una aplicación iOS en el que la aplicación está congelada en memoria pero no ejecuta código. Mostramos cómo funciona Suspended, qué riesgos conlleva la congelación de una aplicación en segundo plano, cómo iOS gestiona la descarga de aplicaciones en Suspended y cómo implementar state restoration para una recuperación sin problemas después de regresar de Suspended.

Puntos clave

  • Suspended — la aplicación está congelada en memoria, no se ejecuta código, la pila de UI se conserva
  • iOS Suspended — un estado único que no existe en Android; el proceso existe pero no está activo
  • Descarga — cuando falta memoria, las aplicaciones en Suspended se eliminan primero, los datos en memoria se pierden
  • State Restoration — mecanismo de iOS para guardar y restaurar la pila de UI después de la descarga
  • didEnterBackground — el último método que se garantiza que se llame antes de Suspended

Suspended — qué es este estado

Suspended es un estado del ciclo de vida de una aplicación iOS en el que la aplicación reside en la RAM del dispositivo pero no ejecuta ningún código. Es el estado final antes de la terminación completa: la aplicación pasa a Suspended desde Background después de completar todas las tareas en segundo plano o después de que expire un tiempo de espera. En Suspended, la aplicación está completamente congelada — todos los hilos están pausados, los temporizadores no funcionan y no hay actividad de red.

Suspended es una característica única de iOS, ausente en el ciclo de vida estándar de Android. La razón radica en las diferentes arquitecturas de gestión de procesos. iOS conserva la imagen de la aplicación en memoria (similar a la hibernación de escritorio) para que cuando el usuario regrese, la interfaz se pueda restaurar instantáneamente sin un inicio en frío. Android no tiene Suspended — un proceso existe y puede ejecutar código (Background) o está terminado (Not Running), aunque Android puede pausar la ejecución de hilos mediante LMK.

Para el usuario, Suspended parece una restauración instantánea: cambian entre aplicaciones usando el App Switcher, y cada aplicación se abre exactamente donde la dejaron. Esto crea la ilusión de que todas las aplicaciones se ejecutan simultáneamente. En realidad, la mayoría están congeladas en Suspended. Un inicio en caliente desde Suspended es muchas veces más rápido que un inicio en frío desde Not Running, porque el código ya está cargado en memoria.

Cómo gestiona el sistema Suspended

iOS monitorea el estado de todas las aplicaciones y decide descargar las aplicaciones en Suspended según la memoria disponible. Cuando la memoria es baja, el sistema comienza a descargar las aplicaciones en Suspended, comenzando por las que han estado más tiempo en este estado. Si la memoria sigue siendo insuficiente, el sistema transiciona aplicaciones desde Background e Inactive a Suspended con posterior descarga. Este proceso es completamente transparente para el usuario — simplemente ven el icono de la aplicación en el App Switcher, que al tocarlo inicia un inicio en frío.

CaracterísticaSuspended (iOS)Background (iOS)Background (Android)
Ejecuta códigoNoSí (limitado)Sí (limitado)
En memoria
Consumo de CPU0%BajoBajo
Inicio en calienteSí — restauración instantáneaSí — mediante InactiveNo — el proceso pudo haber sido eliminado
Tiempo de esperaNo — puede estar en memoria durante horas~30 segundos (después de beginBackgroundTask)Depende de la versión de API
Descarga por el sistemaCuando falta memoriaCuando falta memoria críticamenteLMK (Low Memory Killer)
Regreso al trabajoDesde App Switcher — instantáneamenteDesde App Switcher — mediante InactiveInicio en frío
State RestorationRecomendadoNo requeridoSavedStateHandle

Suspended en iOS: el mecanismo de congelación

En iOS, Suspended se alcanza automáticamente después de completar todas las tareas en segundo plano. El sistema llama a applicationDidEnterBackground, da tiempo para ejecutar beginBackgroundTask (aproximadamente 30 segundos), luego pausa forzosamente todos los hilos y transiciona la aplicación a Suspended. Los objetos en memoria se conservan, pero no se ejecuta ningún código — la aplicación está congelada en su estado actual.

Un punto críticamente importante: applicationDidEnterBackground es el último método garantizado que se llama antes de Suspended. Después de esto, la aplicación no recibe ninguna notificación sobre la descarga de memoria. Si el usuario o el sistema elimina la aplicación mientras está en Suspended, no se llama ni a applicationWillTerminate ni a applicationDidEnterBackground nuevamente. Por lo tanto, todo el guardado de datos debe ocurrir en applicationDidEnterBackground, no en applicationWillTerminate.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    // Última llamada garantizada antes de Suspended
    func applicationDidEnterBackground(_ application: UIApplication) {
        // Guardar todo lo que necesita sobrevivir a la descarga de memoria
        savePersistentState()
        saveNavigationStack()

        // Solicitar tiempo adicional si es necesario
        let task = application.beginBackgroundTask {
            application.endBackgroundTask(task)
        }
    }

    // Regreso de Suspended — inicio en caliente
    func applicationWillEnterForeground(_ application: UIApplication) {
        // La aplicación estaba en Suspended, reanudando trabajo
        print("Regreso de Suspended o Background")
    }

    // Restauración completa después de la descarga de memoria
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Si esto es un inicio en frío después de la descarga de Suspended —
        // restaurar state restoration
        return true
    }

    private func savePersistentState() {
        UserDefaults.standard.set(Date(), forKey: "lastActiveDate")
    }

    private func saveNavigationStack() {
        guard let rootVC = window?.rootViewController else { return }
        // Guardar la pila de navegación actual
        if let navController = rootVC as? UINavigationController {
            let vcClasses = navController.viewControllers.map { type(of: $0) }
            UserDefaults.standard.set(vcClasses.map { NSStringFromClass($0) }, forKey: "navStack")
        }
    }
}

El código muestra el manejo críticamente importante de Suspended en iOS. applicationDidEnterBackground es la última llamada garantizada. Todo el guardado de datos debe ocurrir aquí: estado del usuario, pila de navegación, borradores, temporizadores. applicationWillEnterForeground se llama al regresar de Suspended o Background. didFinishLaunchingWithOptions — solo en inicio en frío, cuando la aplicación fue descargada de memoria después de Suspended.

Suspended en Android — existe un análogo

En Android, no existe un análogo directo de iOS Suspended. Android no congela aplicaciones en memoria conservando el contexto de ejecución. En su lugar, Android mantiene el proceso en segundo plano o lo termina. Sin embargo, en Android 11+ (API 30) se introdujo un mecanismo llamado App Freezer, que suspende la ejecución de procesos en segundo plano mediante la señal SIGSTOP. Esto es funcionalmente similar a Suspended, pero con diferencias importantes.

App Freezer es parte del sistema de gestión de memoria de Android. Cuando una aplicación ha estado en segundo plano durante mucho tiempo sin notificaciones activas, el sistema le envía SIGSTOP, pausando todos los hilos. Cuando la aplicación regresa al primer plano, se envía SIGCONT y la ejecución se reanuda. La diferencia clave con iOS: App Freezer no garantiza la conservación del estado — los datos en memoria pueden perderse si el proceso es eliminado durante la congelación.

En Android, se recomienda usar SavedStateHandle en ViewModel para la conservación automática del estado durante cualquier terminación del proceso. SavedStateHandle guarda datos en un Bundle mediante onSaveInstanceState, que sobrevive tanto a App Freezer como a Process Death. A diferencia de iOS, donde la descarga de Suspended es una situación excepcional, en Android Process Death es un comportamiento normal que debe esperarse siempre.

kotlin
// SavedStateHandle — salvación de Process Death en Android
class CheckoutViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    // Estado que sobrevive al proceso incluso después de App Freezer
    var currentStep: MutableLiveData<Int> =
        savedStateHandle.getLiveData("checkout_step", 1)

    var cartItems: MutableLiveData<List<CartItem>> =
        savedStateHandle.getLiveData("cart_items", emptyList())

    fun proceedToNextStep() {
        currentStep.value = (currentStep.value ?: 0) + 1
    }

    fun addToCart(item: CartItem) {
        val updatedList = (cartItems.value ?: emptyList()) + item
        cartItems.value = updatedList
        savedStateHandle["cart_items"] = updatedList
    }
}

// Guardar en onStop en caso de App Freezer
class MainActivity : AppCompatActivity() {

    override fun onStop() {
        super.onStop()
        // Guardar datos que deben sobrevivir a la congelación
        saveDraftData()
        // Liberar recursos no necesarios en estado congelado
        releaseHeavyResources()
        // Advertir que la aplicación será congelada
        // (Registro para depuración)
        Log.d("Lifecycle", "Activity stopped — posible App Freeze")
    }
}

El código muestra el enfoque para manejar el análogo de Suspended en Android. SavedStateHandle en ViewModel guarda y restaura automáticamente los datos durante Process Death. onStop es el último evento garantizado antes de un posible App Freezer o terminación del proceso. El estado del formulario de pago, la lista de artículos en el carrito — todos estos datos sobreviven a la congelación gracias a SavedStateHandle. Para recursos pesados (bitmaps, cursores de BD), onStop es el lugar para liberar memoria.

State Restoration: recuperación después de Suspended

State Restoration es un mecanismo integrado de iOS para guardar y restaurar el estado de la UI después de que la aplicación es descargada de memoria. Si la aplicación estaba en Suspended y el sistema la descargó, en el próximo inicio en frío state restoration restaura la pila de navegación, la posición de desplazamiento, el estado del formulario y otros elementos de la UI. El usuario regresa a la misma pantalla donde estaba.

State Restoration funciona a través de los protocolos UIViewControllerRestoration y UIStateRestoring. El desarrollador asigna un restorationIdentifier a cada ViewController y View que desea restaurar. Al ir al segundo plano, iOS codifica el estado de estos objetos. Al regresar después de una descarga, iOS crea nuevos objetos y decodifica el estado guardado. Sin state restoration, el usuario verá una pantalla en blanco después de un inicio en frío en lugar de donde se quedó.

swift
import UIKit

class DetailViewController: UIViewController {

    var itemID: String = ""
    var scrollPosition: CGPoint = .zero

    override func viewDidLoad() {
        super.viewDidLoad()
        restorationIdentifier = "DetailViewController"
        restorationClass = type(of: self)
    }

    override func encodeRestorableState(with coder: NSCoder) {
        super.encodeRestorableState(with: coder)
        coder.encode(itemID, forKey: "itemID")
        coder.encode(scrollPosition, forKey: "scrollPosition")
    }

    override func decodeRestorableState(with coder: NSCoder) {
        super.decodeRestorableState(with: coder)
        if let savedID = coder.decodeObject(forKey: "itemID") as? String {
            itemID = savedID
            loadItem()
        }
        if let savedPosition = coder.decodeCGPoint(forKey: "scrollPosition") {
            scrollPosition = savedPosition
            // Restaurar posición después de cargar datos
        }
    }
}

// AppDelegate — activando State Restoration
func application(
    _ application: UIApplication,
    shouldSaveSecureApplicationState coder: NSCoder
) -> Bool {
    return true
}

func application(
    _ application: UIApplication,
    shouldRestoreSecureApplicationState coder: NSCoder
) -> Bool {
    return true
}

El código muestra la implementación de State Restoration en iOS. restorationIdentifier y restorationClass son necesarios para cada ViewController restaurable. encodeRestorableState/decodeRestorableState guardan y cargan datos mediante NSCoder. En AppDelegate, shouldSaveSecureApplicationState y shouldRestoreSecureApplicationState habilitan la conservación cifrada del estado. En iOS 12+, se recomienda usar codificación segura (NSSecureCoding) para la protección de datos.

Mejores prácticas para trabajar con Suspended

La primera regla — nunca asuma que la aplicación regresará de Suspended. El sistema puede descargar la aplicación en cualquier momento. Todos los datos críticamente importantes deben guardarse en almacenamiento persistente antes de la transición a Suspended — es decir, en applicationDidEnterBackground o onStop. UserDefaults, Core Data, File Manager — opciones de almacenamiento adecuadas. La memoria (variables, propiedades) es un almacenamiento no fiable para datos que deben sobrevivir a Suspended.

La segunda regla — libere recursos antes de Suspended. Cierre descriptores de archivos, libere memoria de GPU (Metal, Core Graphics), cierre conexiones de red. Aunque la aplicación no consume CPU en Suspended, los recursos ocupados quedan bloqueados para otras aplicaciones. En iOS, no se pueden mantener sockets abiertos en Suspended — al regresar de Suspended, pueden no ser funcionales, causando errores.

La tercera regla — no coloque lógica dependiente del tiempo esperando regresar de Suspended. Los temporizadores, callbacks y la actividad de red cesan en Suspended. Si la aplicación estuvo en Suspended durante varias horas, un temporizador puede activarse incorrectamente al regresar. Verifique la validez de los datos al regresar — la caché puede estar obsoleta y el token de autorización puede haber expirado.

La cuarta regla — use State Restoration para todas las pantallas, especialmente formularios de entrada, listas con desplazamiento y pantallas de detalle. Sin state restoration, después de regresar de un Suspended descargado, el usuario verá la pantalla inicial de la aplicación en lugar de donde se quedó. Esto degrada la experiencia del usuario y obliga al usuario a repetir acciones.

swift
import UIKit

// Verificación: ¿la aplicación fue descargada de memoria?
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    // Verificar si existe estado guardado
    if UserDefaults.standard.object(forKey: "navStack") != nil {
        // La aplicación fue descargada de Suspended
        // Necesita restaurar el estado
        restoreNavigationStack()
    } else {
        // Inicio en frío limpio desde Not Running
        showOnboardingIfNeeded()
    }
    return true
}

private func restoreNavigationStack() {
    guard let savedStack = UserDefaults.standard.array(forKey: "navStack") as? [String],
          let navController = window?.rootViewController as? UINavigationController
    else { return }

    for vcClassName in savedStack {
        if let vcClass = NSClassFromString(vcClassName) as? UIViewController.Type {
            let vc = vcClass.init()
            navController.pushViewController(vc, animated: false)
        }
    }
}

El código muestra la práctica de determinar si la aplicación fue descargada de Suspended. Verificar UserDefaults para la presencia de una pila de navegación guardada permite distinguir un inicio en frío después de una descarga de un inicio en frío limpio. En el primer caso, se restaura la pila de navegación; en el segundo, se muestra la pantalla de inicio o la principal. Este enfoque complementa el State Restoration integrado para casos donde NSCoder es insuficiente.

Preguntas frecuentes

¿Cuánto tiempo puede permanecer una aplicación en Suspended?

Ilimitado — desde unos segundos hasta varios días. iOS no tiene tiempo de espera para Suspended. La aplicación permanecerá en memoria hasta que el sistema decida descargarla por falta de recursos. En la práctica, las aplicaciones permanecen en Suspended desde 15 minutos hasta varias horas, dependiendo de la RAM del dispositivo y la cantidad de aplicaciones activas.

¿Se llama a applicationWillTerminate al descargar desde Suspended?

No. applicationWillTerminate no se llama cuando la aplicación se descarga de Suspended. El sistema simplemente libera memoria sin notificar a la aplicación. Esta es otra razón por la que todo el guardado de datos debe ocurrir en applicationDidEnterBackground. applicationWillTerminate solo se llama cuando el usuario termina manualmente la aplicación deslizándola fuera del App Switcher.

¿Tiene Android un análogo de Suspended?

No hay un análogo directo. En Android 11+, se introdujo App Freezer, que pausa los procesos en segundo plano mediante SIGSTOP — esto es funcionalmente similar a Suspended. Sin embargo, las aplicaciones de Android deben diseñarse asumiendo Process Death en cualquier momento. Use SavedStateHandle en ViewModel y onSaveInstanceState para guardar el estado que sobrevivirá tanto a App Freezer como a Process Death.

¿Cómo verificar si la aplicación estuvo en Suspended?

En iOS no hay una API directa para verificarlo. Un método indirecto: verificar UserDefaults para la presencia de estado guardado en didFinishLaunchingWithOptions. Si existe estado — la aplicación fue descargada de Suspended y se inicia en frío. Si no existe estado — es un inicio en frío limpio. En SwiftUI, se puede guardar un indicador en scenePhase.background y verificarlo en el próximo inicio.

¿Qué es un snapshot en el contexto de Suspended?

Al hacer la transición a Suspended, iOS toma un snapshot — una captura de pantalla de la UI actual de la aplicación. Esta captura se muestra en el App Switcher y al regresar a la aplicación (como una animación de “descongelación”). Si la aplicación contiene datos confidenciales, el snapshot puede exponerlos. Para protegerlos, use UIApplication.shouldSnapshotSecureApp (iOS 16+) o aplique una superposición de desenfoque en applicationDidEnterBackground.

Resumen

  • Suspended — la aplicación está congelada en memoria de iOS, no se ejecuta código, pero la pila de UI se conserva para restauración instantánea
  • Singularidad de iOS — Suspended no existe en Android; Android usa App Freezer (SIGSTOP) como análogo parcial
  • Descarga — el sistema descarga las aplicaciones en Suspended como primera prioridad cuando falta memoria, sin notificación
  • Guardado — applicationDidEnterBackground es el último método garantizado; todos los datos deben guardarse aquí
  • State Restoration — mecanismo basado en NSCoder para la restauración automática de la UI después de la descarga de Suspended
  • Alternativa en Android — SavedStateHandle + onSaveInstanceState para sobrevivir a Process Death
  • Snapshot — iOS toma una captura de pantalla durante Suspended; los datos confidenciales deben ocultarse mediante superposición de desenfoque o snapshot seguro

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.

Discutir el proyecto

Lea también