Background Task es un mecanismo de iOS que permite a una aplicación completar una operación después de pasar al segundo plano. El sistema asigna tiempo limitado (hasta 30 segundos) para ejecutar la tarea, después de lo cual la aplicación se suspende forzosamente. Según Apple, 2026, el uso de un expiration handler es un requisito obligatorio para completar correctamente una tarea en segundo plano.
Puntos clave
Background Task es un mecanismo programático de iOS que permite a una aplicación extender el tiempo de ejecución después de pasar al segundo plano. Cuando el usuario minimiza la aplicación, el sistema llama a UIApplicationDelegate.applicationDidEnterBackground. Si en ese momento se está realizando una operación crítica (guardar datos, enviar una solicitud), la aplicación puede solicitar tiempo adicional a través de beginBackgroundTask.
Sin usar Background Task, la aplicación se suspende forzosamente en 3–5 segundos después de pasar al segundo plano. Todas las operaciones incompletas se interrumpen: los datos no se guardan, las solicitudes de red se abortan, los estados se pierden. Background Task le da a la aplicación hasta 30 segundos para completar correctamente estas operaciones.
beginBackgroundTask apareció en iOS 4.0 — la primera versión compatible con multitarea. Antes de iOS 4, la aplicación se terminaba por completo al presionar el botón de Inicio. iOS 7 introdujo Background Fetch y la configuración de fondo de URLSession. A partir de iOS 13, Apple recomienda BGTaskScheduler para nuevos proyectos, pero beginBackgroundTask sigue siendo relevante para operaciones a corto plazo.
beginBackgroundTask es un método de UIApplication que registra una tarea y devuelve un identificador único UIBackgroundTaskIdentifier. El sistema aumenta el temporizador de ejecución en segundo plano. Cuando expira el tiempo, se llama al expiration handler, después de lo cual la aplicación debe llamar a endBackgroundTask(identifier:) para completar correctamente la tarea.
Paso 1 — la aplicación recibe la notificación didEnterBackground. Paso 2 — se llama a beginBackgroundTask(expirationHandler:). Paso 3 — se realiza la operación crítica (guardado, solicitud de red). Paso 4 — al finalizar, se llama a endBackgroundTask(identifier:). Si la operación no se completa en 30 segundos — el sistema llama al expiration handler, y la aplicación debe finalizar la tarea inmediatamente.
var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
func startBackgroundTask() {
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
// Expiration handler
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
}
func finishBackgroundTask() {
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
La propiedad backgroundTimeRemaining devuelve la cantidad de segundos restantes antes de que la tarea en segundo plano se termine forzosamente. El valor disminuye en tiempo real. Si la aplicación no está en segundo plano — devuelve DBL_MAX. Use esta propiedad para adaptar el comportamiento: cuando queden menos de 5 segundos, interrumpa las operaciones largas y guarde el progreso.
Una aplicación puede registrar varias Background Tasks simultáneamente. Cada tarea obtiene su propio identificador. El tiempo total de ejecución es acumulativo — si se registran 3 tareas, la aplicación puede obtener hasta 90 segundos. Sin embargo, el sistema puede terminar la aplicación antes si se agotan los recursos o se excede el límite de batería.
Expiration handler es un bloque de código que el sistema llama cuando expira el tiempo asignado para la tarea en segundo plano. Tener un expiration handler es un requisito obligatorio de Apple. Sin él, la aplicación puede ser terminada forzosamente por el sistema y los datos pueden perderse.
El expiration handler debe realizar acciones mínimas para guardar el estado de la aplicación: guardar los datos actuales en almacenamiento persistente, llamar a endBackgroundTask con el identificador correspondiente y establecer el identificador en .invalid. Dentro del expiration handler está prohibido iniciar nuevas operaciones largas — el tiempo de ejecución está limitado a 1–2 segundos.
func handleExpiration() {
// Guardando el progreso de ejecución
saveProgressToUserDefaults()
// Cancelando solicitudes de red activas
currentTask?.cancel()
// Finalizando Background Task
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
// Registro con manejador de expiración
backgroundTaskID = UIApplication.shared.beginBackgroundTask(
withName: "SaveDocument",
expirationHandler: handleExpiration
)
El error más común es no llamar a endBackgroundTask dentro del expiration handler. En este caso, el sistema continúa considerando la tarea activa, la aplicación no pasa al estado Suspended y la batería se agota. El segundo error es iniciar operaciones largas dentro del expiration handler. El sistema puede terminar la aplicación antes de que se completen, y los datos se perderán.
En el expiration handler, el tiempo de ejecución es críticamente limitado — típicamente menos de 1 segundo. Por lo tanto, dentro del handler no se pueden realizar: cálculos complejos, solicitudes de red, escritura de grandes volúmenes de datos en CoreData. Solo operaciones atómicas: escribir una clave en UserDefaults, establecer un indicador de estado, llamar a endBackgroundTask.
Revisemos una implementación completa de Background Task para guardar un documento cuando la aplicación pasa al segundo plano. El ejemplo incluye registro de tarea, realización de la operación con verificación del tiempo restante y finalización correcta mediante endBackgroundTask.
Al pasar al segundo plano, la aplicación inicia el guardado de un documento grande. Background Task proporciona hasta 30 segundos para la operación. Si el tiempo se agota — el expiration handler guarda los resultados intermedios. Después de completar el guardado, se llama a endBackgroundTask para liberar recursos.
class DocumentManager {
private var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid
func saveDocumentInBackground(document: Document) {
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
self.saveProgress(document)
self.endBackgroundTask()
}
DispatchQueue.global().async {
document.save()
self.endBackgroundTask()
}
}
private func endBackgroundTask() {
UIApplication.shared.endBackgroundTask(backgroundTaskID)
backgroundTaskID = .invalid
}
}
Las solicitudes de red en segundo plano requieren atención especial — el expiration handler puede interrumpir la solicitud antes de recibir una respuesta. Use URLSession con dataTask y verifique backgroundTimeRemaining antes de enviar. Si quedan menos de 5 segundos — posponga el envío hasta la próxima activación de la aplicación.
func sendCriticalData(data: Data) {
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
// Guardando datos para reenvío
saveForRetry(data)
self.endBackgroundTask()
}
let task = URLSession.shared.dataTask(with: request) { _, _, error in
if error != nil {
saveForRetry(data)
}
self.endBackgroundTask()
}
task.resume()
}
Para operaciones largas, monitoree UIApplication.shared.backgroundTimeRemaining. Si el valor cae por debajo de un umbral (10 segundos), interrumpa la operación actual y comience a guardar resultados intermedios. Esto permite una finalización correcta antes de que se llame forzosamente al expiration handler.
Background Task es un mecanismo potente, pero su uso incorrecto provoca problemas de batería y rendimiento. Seguir las recomendaciones de Apple y las prácticas comprobadas de la comunidad ayudará a evitar errores comunes y garantizar un funcionamiento estable de la aplicación.
Complete la Background Task lo más rápido posible. Cada segundo de ejecución en segundo plano consume batería. Tiempo óptimo — menos de 5 segundos. Si la operación toma más — considere usar BGTaskScheduler o Background Modes. No prolongue artificialmente la tarea mediante llamadas a beginBackgroundTask sin necesidad real.
Almacene UIBackgroundTaskIdentifier como una propiedad de clase o estructura. Nunca lo pase como una variable global — esto genera conflictos con tareas múltiples. Establezca el identificador en .invalid después de llamar a endBackgroundTask para evitar una finalización doble.
En el Simulador de Xcode, cambie la aplicación al segundo plano mediante el botón de Inicio (Command + Shift + H). Use Debug — Simulate Background Fetch para probar la activación en segundo plano. Para simular la expiración del tiempo, establezca la Variable de Entorno BACKGROUND_TASK_SIMULATE_EXPIRATION = YES — el expiration handler se llamará en 5 segundos.
// Verificando el tiempo restante antes de iniciar la operación
let remaining = UIApplication.shared.backgroundTimeRemaining
guard remaining > 10.0 else {
// Tiempo insuficiente — posponer la tarea
scheduleForNextLaunch()
return
}
// Ejecutando la operación con control de tiempo
backgroundTaskID = UIApplication.shared.beginBackgroundTask {
saveProgress()
self.endBackgroundTask()
}
El expiration handler captura self — esto puede crear un ciclo de retención si backgroundTaskID se almacena como una propiedad del mismo objeto. Use [weak self] en el cierre o almacene el identificador por separado. Un ciclo de retención provoca una fuga de memoria: el objeto no se liberará hasta que termine la aplicación.
Con el lanzamiento de iOS 13, Apple presentó BGTaskScheduler — un reemplazo moderno para la antigua API de Background Task. Ambos mecanismos resuelven tareas similares, pero BGTaskScheduler proporciona más control y flexibilidad. Comprender las diferencias ayudará a elegir la herramienta adecuada para un escenario específico.
| Característica | Background Task | BGTaskScheduler |
|---|---|---|
| Versión iOS | 4.0+ | 13.0+ |
| Tiempo máximo | 30 segundos | 30 s / 10 min (processing) |
| Iniciación | didEnterBackground | Programación + sistema |
| Garantía de ejecución | Solo al pasar a segundo plano | En cualquier momento conveniente para el sistema |
| Expiration handler | Sí, obligatorio | Sí, mediante task.expirationHandler |
| Internet | Requerido al inicio | Disponible mediante requiresNetworkConnectivity |
| Carga | No requerida | Opcional para processing |
beginBackgroundTask es adecuado para operaciones a corto plazo que deben ejecutarse inmediatamente al pasar al segundo plano: guardar estado, completar una solicitud de red, almacenar datos en caché. La API es simple y no requiere configuración de Info.plist ni registro de identificadores. Ideal para operaciones que toman menos de 10 segundos.
BGTaskScheduler es adecuado para tareas que pueden realizarse en cualquier momento conveniente: sincronización periódica, limpieza de caché, actualización de widgets. El sistema mismo selecciona el momento óptimo considerando el comportamiento del usuario y el estado de la batería. Para operaciones largas (hasta 10 minutos), use BGProcessingTask.
Ambas API se pueden usar en la misma aplicación. Background Task — para operaciones inmediatas al pasar a segundo plano (guardar un borrador). BGTaskScheduler — para actualizaciones programadas (sincronización cada 6 horas). La separación de responsabilidades garantiza la preservación correcta de datos y un mantenimiento en segundo plano eficiente energéticamente.
Preguntas frecuentes
Sí, beginBackgroundTask se puede llamar en cualquier momento durante la ejecución de la aplicación. Sin embargo, la asignación de tiempo del sistema solo comenzará después de pasar al segundo plano. Si la aplicación está en primer plano, llamar a beginBackgroundTask no tiene efecto — backgroundTimeRemaining devuelve DBL_MAX, y la tarea se activará al pasar a segundo plano.
Si no se llama a endBackgroundTask, el sistema continúa considerando la aplicación activa en segundo plano. Después de 30 segundos, se llamará al expiration handler, pero si este también carece de endBackgroundTask — la aplicación permanece en memoria, agotando la batería. En iOS 13+, el sistema termina forzosamente dicha aplicación después de 3 minutos.
El tiempo estándar es de 30 segundos. Solo se puede extender mediante Background Modes: Audio (reproducción), Location (geolocalización), Bluetooth (BLE). O mediante BGProcessingTask (iOS 13+) — hasta 10 minutos con carga y Wi-Fi. beginBackgroundTask por sí mismo no proporciona una forma de aumentar el límite.
Sí, iPadOS es totalmente compatible con beginBackgroundTask con las mismas limitaciones que iOS. En iPad con Stage Manager, la aplicación puede permanecer más tiempo en memoria — el sistema suspende las aplicaciones con menos frecuencia debido a una mayor RAM. Pero el límite de 30 segundos para tareas en segundo plano se mantiene.
Conecte el dispositivo a Xcode, inicie la aplicación, minimícela — los registros del sistema aparecerán en la consola. Use sysdiagnose para recopilar registros detallados: active forzosamente sysdiagnose desde el dispositivo (Subir Volumen + Bajar Volumen + Encendido). En el Navegador de Depuración de Xcode, monitoree la actividad de las tareas en segundo plano.
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