Cómo usar beginBackgroundTaskWithExpirationHandler para ejecutar una tarea en iOS

En mi aplicación, estoy cargando imágenes al servidor desde el iPhone. Mientras se sincroniza, si el usuario presiona el botón de inicio, la aplicación se cerrará.

Quiero que la aplicación se ejecute en segundo plano hasta que finalice la sincronización.

Mi pregunta es: ¿cómo puedo agregar la tarea que se está ejecutando actualmente con ” beginBackgroundTaskWithExpirationHandler “?

Por favor comparte tus ideas.

A pesar de su nombre, beginBackgroundTaskWithExpirationHandler: realidad no “comienza” una tarea. Podría pensarse mejor como “registrarse …” en lugar de “comenzar …”. Le está diciendo al sistema que está en el medio de hacer algo que le gustaría completar si está bien.

Varios puntos:

  • En casi todos los casos, desea llamar a beginBackgroundTaskWithExpirationHandler: cuando comienza a hacer lo que desea hacer, y luego endBackgroundTask: cuando endBackgroundTask: . Casi nunca los llama en el punto en que el usuario presiona el botón de Inicio (a menos que ese sea el punto cuando inicia la tarea, como guardar algo en el servidor).

  • Puede tener tantas “tareas en segundo plano” como desee abrir a la vez. No cuestan nada Son como contar retenciones. Siempre y cuando todavía tenga uno abierto (un “comienzo” que no llegó a su “final”), entonces el sistema considerará que es una solicitud de más tiempo. Hay muy poco costo para llamar a los métodos de “inicio” y “fin”, así que úselos para poner entre corchetes cualquier cosa que desee tiempo extra para terminar.

  • No hay forma de estar seguro de que terminará su sincronización. Estos métodos solo hacen una solicitud. El sistema operativo aún puede denegar esa solicitud. El sistema operativo aún puede matarte en cualquier momento si necesita algunos recursos adicionales. El sistema operativo no es infinitamente paciente; si toma demasiado tiempo (normalmente unos 10 minutos), le matará de todos modos después de llamar a su controlador de caducidad. El sistema operativo puede matarte porque el teléfono está apagado. Tu aplicación debe ser capaz de lidiar con no llegar a terminar. El sistema operativo solo te brinda esta capacidad para que puedas mejorar la experiencia del usuario.

Utilicé el siguiente código para el manejador de tareas en segundo plano:

 __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ NSLog(@"Background Time:%f",[[UIApplication sharedApplication] backgroundTimeRemaining]); [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; backgroundTaskIdentifier = UIBackgroundTaskInvalid; }]; 

Así es como utilicé beginBackgroundTaskWithExpirationHandler, incluida la llamada al método que se realizará en segundo plano. Esto incluye código para iniciar la nueva tarea asíncrona. Entonces, no es exactamente lo que se pregunta en la pregunta. Agregando el código a continuación, pensando que alguien podría estar buscando este escenario:

 - (void)didReceiveObjList:(CFDataRef)message { // Received Object List. Processing the list can take a few seconds. // So doing it in separate thread with expiration handler to ensure it gets some time to do the task even if the app goes to background. UIApplication *application = [UIApplication sharedApplication]; __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{ [application endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self processObjList:message]; [application endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; }); NSLog(@"Main Thread proceeding..."); } 

Echa un vistazo a esta página, Apple describe cómo mantener la aplicación iOS no suspendida mientras está en segundo plano. Documentación de Apple

Y aquí está lo que he implementado:

 UIBackgroundTaskIdentifier bgTask; - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restre your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. NSLog(@"=== DID ENTER BACKGROUND ==="); bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ NSLog(@"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'"); // [self askToRunMoreBackgroundTask]; This code seems to be unnecessary. I'll verify it. }]; if (bgTask == UIBackgroundTaskInvalid) { NSLog(@"This application does not support background mode"); } else { //if application supports background mode, we'll see this log. NSLog(@"Application will continue to run in background"); } } /* - (void)askToRunMoreBackgroundTask { [[UIApplication sharedApplication] endBackgroundTask:bgTask]; NSLog(@"restart background long-running task"); bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ NSLog(@"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'"); [self askToRunMoreBackgroundTask]; }]; } */ - (void)applicationWillEnterForeground:(UIApplication *)application { NSLog(@"=== GOING BACK FROM IDLE MODE ==="); //it's important to stop background task when we do not need it anymore [[UIApplication sharedApplication] endBackgroundTask:UIBackgroundTaskInvalid]; } 

Aquí hay una pequeña variación de las otras respuestas que estoy usando cuando la aplicación está en segundo plano y necesito hacer algo en el hilo principal:

 - (void)applicationWillResignActive:(UIApplication *)application { UIApplication *app = [UIApplication sharedApplication]; // Register auto expiring background task __block UIBackgroundTaskIdentifier bgTaskId = [app beginBackgroundTaskWithExpirationHandler:^{ [app endBackgroundTask:bgTaskId]; bgTaskId = UIBackgroundTaskInvalid; }]; // Execute background task on the main thread dispatch_async( dispatch_get_main_queue(), ^{ // ------------------ // DO SOMETHING INVOLVING THE WEBVIEW - WHICH MUST OCCUR ON THE MAIN THREAD! // ------------------ [app endBackgroundTask:bgTaskId]; bgTaskId = UIBackgroundTaskInvalid; }); } 

Debe ejecutar su tarea después de beginBackgroundTaskWithExpirationHandler o capturar la notificación cuando la aplicación cambie el estado de la aplicación a fondo y luego cancelar la tarea actual y ejecutar nuevamente con beginBackgroundTaskWithExpirationHandler .

    Intereting Posts