Programación de finalización de tareas en segundo plano de iOS

Estoy tratando de agregar soporte para completar una tarea después de salir del primer plano para mi aplicación iOS. Todos los tutoriales que vi en Internet me indican que escriba algo como esto en el Delegado de la aplicación:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    if ([[UIDevice currentDevice] isMultitaskingSupported]) {
        UIApplication *application = [UIApplication sharedApplication];
        __block UIBackgroundTaskIdentifier background_task;
        background_task = [application beginBackgroundTaskWithExpirationHandler: ^ {
            [application endBackgroundTask: background_task];
            background_task = UIBackgroundTaskInvalid;
        }];

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            //DO STUFF IN BACKGROUND HERE
            MyTask *task = [[MyTask alloc] initWithURL:@"http://google.com"];
            [task setDelegate:self];
            [task start];

            [application endBackgroundTask: background_task];
            background_task = UIBackgroundTaskInvalid;
        });
    }
}

La tarea puede comenzar, pero después de que comienza, la siguiente línea se procesa y mi aplicación se cancela. soy capaz de decir cuando MyTask se detiene debido a una llamada de delegado, pero ¿cómo cambio mi programa para que la tarea en segundo plano se establezca como no válida después de que se llame al delegado? ¿Me movería?

[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;

a la función de delegado, o necesito hacer algo más.

Gracias de antemano por tu ayuda, Guvvy

preguntado el 12 de junio de 12 a las 22:06

2 Respuestas

Ya estás en un hilo de fondo por tu llamada a dispatch_async. Ese método regresará inmediatamente, pero su bloque continuará ejecutándose.

Su problema parece ser que su método de inicio ejecuta otro proceso asincrónico, por lo que ese método regresa de inmediato y su tarea en segundo plano se elimina antes [task start] es capaz de hacer cualquier cosa significativa.

Si vas por la ruta de matar background_task en su delegado, también tendrá que crear un ivar para almacenar background_task para que sus métodos delegados puedan acceder a él. Eso parece un poco de mano dura.

Como ya está en un hilo de fondo, le sugiero que refactorice [task start] por lo que es sincrónico. De esa manera, todo el trabajo significativo se realizará antes de que se procese la siguiente línea y background_task es asesinado. Esto parece más limpio, y todo para su tarea en segundo plano está muy bien envuelto en el bloque enviado a dispatch_async.

Respondido el 06 de Septiembre de 12 a las 22:09

hola @ djibouti33, ¿puedes explicar qué estás tratando de decir? "Mi sugerencia sería que refactorizaras [inicio de la tarea] para que sea sincrónico". . Estoy usando un método de llamada NStimer después de 600 segundos. pero bgTask caduca instantáneamente cuando la aplicación pasa a segundo plano - vishwa.deepak

el método [inicio de la tarea] era un método asíncrono, lo que significa que regresó inmediatamente (antes de que se realizara cualquier trabajo), y luego se eliminó background_task. Al hacerlo sincrónico, el método bloquearía cualquier otra ejecución hasta que se completara, y luego background_task podría eliminarse con éxito y en el momento correcto. - yibuti33

Puede eliminar completamente el siguiente código:

[application endBackgroundTask: background_task];
background_task = UIBackgroundTaskInvalid;

Cuando su tarea expire, iOS llamará a su método handlerExpiration para eliminarla. Para mayor información por favor visite Fondo para iOS

Respondido el 24 de Septiembre de 13 a las 10:09

Esto es simplemente incorrecto. Si no llama a endBackgroundTask: dentro del tiempo especificado, su aplicación se eliminará por completo, en lugar de permanecer suspendida y "lanzarse" más rápido a los ojos del usuario. Ver la documentación desarrollador.apple.com/library/ios/documentation/uikit/reference/…: - Maciej Swic

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.