Creo que la razón por la que te cuesta encontrar una respuesta definitiva es que el concepto de una aplicación "en funcionamiento" es diferente aquí de lo que muchos esperan. Un usuario no técnico puede tener una idea de lo que significa "ejecutar", un programador de PC de la "vieja escuela" puede tener una idea diferente - y luego está lo que realmente sucede en iOS, que probablemente sólo Apple y los desarrolladores de aplicaciones tienen que tratar realmente.
En un PC tradicional, encontrarás que tienes un programa ejecutable en el disco que inicias - y ahora el programa está "corriendo". Aquí "corriendo" significa que el programa esperará que su hilo principal de ejecución sea programado periódicamente para ejecutarse en la CPU - lo que significa que su propio código de programa se ejecutará en la CPU real y tendrá algún poder sobre lo que realmente sucede.
En un PC tradicional podrías tener una aplicación de este tipo en funcionamiento con una interfaz gráfica de usuario en una ventana. Ya sea que esa ventana esté en primer plano, en segundo plano, o incluso minimizada (es decir, no visible en absoluto) - usted todavía tiene el código de programación siendo programado periódicamente 1 para que se ejecute en la CPU. La aplicación es, por así decirlo, libre de hacer lo que quiera. La aplicación puede tener una prioridad menor en segundo plano, y puede que no se programe con tanta frecuencia o durante tanto tiempo como cuando está en primer plano, pero sigue siendo básicamente lo mismo.
Todavía en un PC tradicional, podrías poner todo el PC en modo de suspensión. Hay muchos tipos diferentes de estados de suspensión con diferentes impactos en el sistema:
Para los estados de reposo S1, S2 y S3, la aplicación todavía tiene su estado en la RAM, pero no tendrá su código de programa programado periódicamente para ejecutarse en la CPU mientras está en reposo. Esto es básicamente todo lo que realmente sucede desde el contexto de la aplicación 2 aunque desde el contexto del sistema operativo muchas cosas tienen que tener lugar al despertar (es decir, los controladores tienen que reiniciar los periféricos, etc.).
Para el estado de reposo S4, el estado de la aplicación se guarda en el disco - aunque esto ocurre de forma transparente para la aplicación. Ya no está programada para ejecutarse en la CPU (obviamente). Cuando el PC se despierta, el estado se restaura en la memoria y la aplicación puede volver a ejecutarse programando su código de programa para que se ejecute de nuevo en la CPU.
Para el estado de energía del S5, el sistema está básicamente apagado y desconectado. En este caso, el sistema operativo no guarda el estado de la aplicación en el disco automáticamente. La aplicación debe tener por sí misma el estado guardado para poder reanudar donde lo dejó cuando el sistema se enciende de nuevo. En muchos sistemas operativos, encontrarás que es común que las aplicaciones no hagan esto - o al menos no lo hacen de manera transparente. Por ejemplo, si apagas tu sistema con tu juego favorito en marcha, no puedes esperar que el juego esté en marcha y en el mismo lugar cuando vuelvas a encender el sistema.
Ahora pasaré a las aplicaciones en iOS. Al igual que los estados de energía Sx de los que hablamos antes (que son de todo el sistema), una aplicación en iOS también pasará por varios estados durante su vida. Específicamente las aplicaciones se componen de escenas 2 que puede estar en uno de los siguientes estados:
- No inscritos
- Primer plano e inactivo
- Primer plano y activo
- Antecedentes
- Suspendido
Que consideres que la aplicación está "funcionando" en cualquiera de estos estados depende realmente de tu punto de vista. Por ejemplo, un usuario no técnico podría pensar en esto de forma diferente a un desarrollador de aplicaciones.
Si vemos un ejemplo en el que se inicia una aplicación por primera vez, esto es lo que ocurre:
Cuando toques un icono en la pantalla de inicio para "ejecutar" tu aplicación, una escena específica de la misma pasará primero al estado "sin conexión". Esto significa que partes del código ejecutable de la aplicación se cargan en la RAM, se configura un bucle de eventos y se activa una funcionalidad específica y limitada en el código del programa. Este código particular, en la primera ejecución, normalmente no hará casi nada en sí mismo (es decir, activará algún código UIKit en los marcos del sistema, por ejemplo, pero no mucho código específico de la aplicación). Nada es visible en la pantalla para el usuario.
Poco después, la escena pasará al estado "Primer plano e inactivo". Aquí la aplicación ejecutará su propio código para configurar los elementos de la interfaz de usuario, iniciar temporizadores, adquirir recursos compartidos, etc. - pero todavía no se muestra nada en pantalla y no se da ninguna entrada de usuario al programa.
Poco después, la escena pasará al estado "Primer plano y activo". Ahora sus elementos de interfaz de usuario serán visibles en la pantalla y las entradas del usuario (como los toques) se envían al bucle de eventos de la aplicación. El código de la aplicación se programa periódicamente para su ejecución.
Algún tiempo después, iOS puede volver a pasar la escena al estado "Primer plano e inactivo". Por ejemplo, si el usuario decide cambiar de aplicación. Una vez más, los eventos de entrada del usuario no se envían a la aplicación, sino que el propio código de la aplicación se programa periódicamente con el fin de pausar las operaciones de trabajo, como por ejemplo guardar los datos del usuario en el almacenamiento permanente, detener los temporizadores, pausar los hilos que vacían las colas de tareas, detener la actualización de las animaciones, etc.
Si la escena se convirtió en "Primer plano e inactiva" sólo temporalmente debido, por ejemplo, a una ventana emergente modal del sistema (como, por ejemplo, un mensaje de que queda un 10% de batería), la escena puede volver a pasar pronto a "Primer plano y activa". Sin embargo, si se debe a que el usuario ha cambiado de aplicación, la escena pasará a estar en "segundo plano".
Cuando se pasa al estado de "Fondo", el código propio de la aplicación se programará para su ejecución sólo durante un tiempo muy limitado (normalmente 5 segundos, pero una aplicación puede solicitar una extensión). Aquí se supone que la aplicación libera cualquier objeto de datos de gran tamaño en la memoria (como, por ejemplo, imágenes y archivos de audio cargados anteriormente desde el almacenamiento), libera cualquier recurso compartido que tenga (como, por ejemplo, la cámara, la libreta de direcciones o muchos otros tipos de recursos compartidos). También se supone que limpia su interfaz de usuario para "desordenarla" y eliminar cualquier información sensible 3 . Después de un corto tiempo, iOS dejará de programar el código de la aplicación para su ejecución, y tomará una "captura de pantalla" (recuerde que la interfaz de usuario no se muestra en la pantalla, por lo que está tomando una copia de mapa de bits de lo que se habría mostrado en la pantalla, si hubiera estado en la pantalla). Esta captura de pantalla es lo que se presentará al usuario como la "aplicación en ejecución" en el conmutador de aplicaciones, por ejemplo. Los elementos reales de la interfaz de usuario podrían haber sido purgados de la memoria, pero la captura de pantalla seguirá teniendo el mismo aspecto.
Una cosa importante que hay que tener en cuenta es que las aplicaciones pueden decirle a iOS que admiten casos de uso específicos que les harán beneficiarse de que su código se programe para su ejecución incluso cuando se encuentre en el estado de "fondo". La aplicación no decide por sí misma cuándo se ejecuta su código; eso lo decide iOS en función de los casos de uso para los que se haya registrado la aplicación. Por ejemplo, puede ser que la aplicación sea una aplicación de correo electrónico que haya solicitado que se le permita comprobar si hay correo nuevo mediante un temporizador. Podría ser una aplicación que ha solicitado un tiempo de ejecución cuando la ubicación geográfica del usuario cambia una cierta cantidad. Hay varios otros casos de uso, como por ejemplo un receptor de notificaciones push, aplicaciones que reproducen audio que el usuario quiere seguir reproduciendo cuando la aplicación está en segundo plano, etc.
En el estado de "fondo", parte del código del programa suele seguir en la RAM, pero la mayoría de sus recursos más grandes no lo están. La aplicación puede realizar algunas funciones limitadas, pero controladas por iOS, no por ella misma. La interfaz de usuario es básicamente una captura de pantalla.
Más tarde, la escena se puede suspender a discreción de iOS. Esto significa que se le da tiempo a la aplicación para que ejecute código que permita conservar su estado en el almacenamiento permanente para poder restaurar la aplicación al mismo estado más adelante. Esto se hace para dar la ilusión de que la aplicación está siempre en funcionamiento. En el caso de las aplicaciones que utilizan las herramientas de Apple, el sistema puede hacer esto de forma más o menos automática sin que el desarrollador de la aplicación tenga que hacer mucho. Sin embargo, para algunas aplicaciones, el desarrollador tiene que hacer mucho trabajo para poder persistir correctamente su estado.
Ahora, cuando la aplicación está "Suspendida", iOS es libre de eliminarla completamente de la RAM. Aunque para el usuario, muy poco o nada sucede visiblemente cuando la aplicación está suspendida. Lo más importante es que iOS se aferra al estado guardado, que se conserva también cuando se reinicia el teléfono. Se descarta cuando el usuario utiliza el conmutador de aplicaciones para forzar la salida de la aplicación, y si la aplicación se bloquea en el lanzamiento (indicando un error en la aplicación - esto se hace para evitar que la aplicación se cuelgue en cada lanzamiento).
Cuando el usuario vuelve a una aplicación en estado "Suspendido", la escena vuelve a entrar en el estado de desvinculación. La diferencia con el "nuevo comienzo" es que esta vez, la app también recibe su estado conservado. La aplicación puede ahora utilizar estos datos para configurar los elementos de la interfaz de usuario, el estado interno, etc., de manera que la aplicación se vea para el usuario exactamente como lo hacía antes de ser suspendida.
Algunos desarrolladores sólo utilizan las herramientas propias de Apple en un asunto en el que esto sucede sin esfuerzo o son hábiles en la implementación de esta restauración por sí mismos. Esto hace que el usuario no pueda distinguir la diferencia entre una aplicación que pasa del estado de "fondo" al estado de primer plano, y una aplicación que pasa del estado de "suspensión" al estado de primer plano.
Sin embargo, algunos desarrolladores no proporcionan esta restauración sin fisuras. En el caso más básico (es decir, no hacen nada), la aplicación se "reiniciará" esencialmente y parecerá que se ha forzado su salida y se ha iniciado de nuevo.
Esto explica en parte la razón por la que algunas apps parecen estar "funcionando todo el tiempo", y otras parecen estar "paradas" y "reiniciadas". No significa necesariamente que iOS haya "decidido abandonar" esa app más que otras, sino que la propia app no se construyó con el mismo cuidado o fue, por otras razones, incapaz de preservar y restaurar su estado.
Ten en cuenta que iOS puede suspender las aplicaciones por varias razones que no sean el reinicio del teléfono. Por ejemplo, una aplicación puede estar en segundo plano y suspendida para liberar memoria u otros recursos que puedan ser utilizados por otros programas. También pueden volver a suspenderse cuando los recursos son menos escasos.
Básicamente, las aplicaciones pueden pasar a segundo plano y suspenderse sin que el usuario no técnico se dé cuenta de nada. La aplicación seguirá teniendo el mismo aspecto en el conmutador de aplicaciones, y el usuario puede volver a utilizarla sin que haya necesariamente ninguna diferencia entre una aplicación suspendida y otra no suspendida. Tenga en cuenta que, a menudo, una aplicación suspendida tardará un poco más en aparecer que una aplicación no suspendida.
Para resumir todo esto, la definición de cuándo un programa está "en marcha" es contextual y puede ser bastante compleja. ¿Consideraría el usuario medio que un programa de PC con una ventana minimizada está "en ejecución"? - Si ese PC pasa temporalmente al estado de reposo S1, ¿el programa sigue "funcionando"? Se podría argumentar que no, pero ¿se podría argumentar que el programa ha "abandonado"?
Del mismo modo, un usuario no técnico podría considerar que una aplicación de iOS se ejecuta en cualquiera de los estados mencionados, siempre y cuando se conserve su estado. El usuario puede cambiar a la aplicación y ésta responderá y se verá como se espera, no se "reinicia" (como si volviera a empezar desde cero). Obviamente, algunos podrían considerar que la aplicación no se está ejecutando cuando el teléfono está apagado... pero desde el punto de vista de la propia aplicación, en realidad no "sabe" si el teléfono se ha apagado o no.
1: Tenga en cuenta que el programa puede haber pedido al sistema operativo específicamente que no lo programe de nuevo a menos que ocurra algún evento.
2: Estoy hablando de iOS 13 y más recientes aquí - es ligeramente diferente en iOS 12 y anteriores, donde esto no se maneja en una base por escena, sino en una base por UIApplication.
3: Esto explica por qué algunas aplicaciones aparecen en el conmutador de aplicaciones como "en blanco" o con un "color sólido" solamente. Algunas aplicaciones cambian a propósito su interfaz de usuario para que se vea así justo antes de que se tome la captura de pantalla, con el fin de proteger la información sensible de las miradas indiscretas. Esto no significa que la aplicación se haya "borrado de la memoria" o que esté "menos en funcionamiento" (si eso tiene algún sentido) que otras aplicaciones.