AlamoFire Descargar en Sesión de Fondo


Estoy usando Alamofire dentro de una nueva aplicación (Un ejemplo de Gestor de descargas basado en Alamofire) Necesito algunas aclaraciones sobre la descarga de archivos usando la sesión de fondo. Necesito anular SessionDelegate para que funcione? O simplemente backgroundCompletionHandler?

Normalmente, ¿cuáles son los pasos para manejar las descargas en segundo plano usando Alamofire? Y cómo puedo manejar el caso en el que mi aplicación es relauch, con descargas en flujo. Gracias y saludos.

Author: LastMove, 2015-05-09

3 answers

Actualizar

Basado en este increíble tutorial, he reunido un proyecto de ejemplo disponible en GitHub. Tiene un ejemplo para la gestión de sesiones en segundo plano.

De acuerdo con la Guía de Programación del Sistema de Carga de URL de Apple :

Tanto en iOS como en OS X, cuando el usuario reinicia su aplicación, su aplicación debe crear inmediatamente objetos de configuración de fondo con el los mismos identificadores que cualquier sesión que tuviera tareas pendientes cuando su la aplicación se ejecutó por última vez, luego cree una sesión para cada uno de esos objetos de configuración. Estas nuevas sesiones son igualmente automáticamente vuelvan a asociar con la continua actividad de fondo.

Así que aparentemente al usar las instancias de configuración de sesión en segundo plano apropiadas, sus descargas nunca estarán "en flujo".

También he encontrado esta respuesta realmente útil.

Respuesta original

De la página de GitHub de Alamofire :

Las aplicaciones pueden crear gestores de fondo y efímeros sesiones, así como nuevos gestores que personalizan la sesión predeterminada configuración, como para encabezados predeterminados (HTTPAdditionalHeaders) o intervalo de tiempo de espera (timeoutIntervalForRequest).

De forma predeterminada, los métodos de nivel superior utilizan una instancia compartida Manager con configuración de sesión predeterminada. Sin embargo, puede crear un administrador con la configuración de sesión en segundo plano de la siguiente manera:

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.example.app.background")
let manager = Alamofire.Manager(configuration: configuration)

Puedes luego haga peticiones usando esta instancia Manager.

manager.startRequestsImmediately = true
let request = NSURLRequest(URL: NSURL(string: "your.url.here")!)
manager.request(request)

Al observar su implementación, también tiene una propiedad llamada backgroundCompletionHandler, por lo que puede agregar un bloque de finalización:

manager.backgroundCompletionHandler = {
        // do something when the request has finished
    }
 28
Author: József Vesza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:13

En realidad es muy fácil con Alamofire:

1) su Alamofire.El administrador debe configurarse con un identificador de sesión en segundo plano:

class NetworkManager {
    ...
    private lazy var backgroundManager: Alamofire.SessionManager = {
        let bundleIdentifier = ...
        return Alamofire.SessionManager(configuration: URLSessionConfiguration.background(withIdentifier: bundleIdentifier + ".background"))
    }()
    ...
}

2) en la Aplicación Delegate implemente application(_:handleEventsForBackgroundURLSession:completionHandler: y pase el controlador de finalización a Alamofire.SessionManager.backgroundCompletionHandler.

En mi caso, el método delegado de la aplicación se parece a

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
    NetworkManager.default.backgroundCompletionHandler = completionHandler
}

Y mi administrador de red tiene una propiedad calculada como esta para establecer la propiedad del Administrador:

var backgroundCompletionHandler: (() -> Void)? {
    get {
        return backgroundManager.backgroundCompletionHandler
    }
    set {
        backgroundManager.backgroundCompletionHandler = newValue
    }
}
 23
Author: Luca Torella,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-12 09:10:34

Estuve buscando la solución bastante tiempo. Hasta leer el artículo mencionado anteriormente. El problema para mí era que tenía que habilitar La comunicación externa accesoria

introduzca la descripción de la imagen aquí

Todo lo demás se hizo como se describió anteriormente. AppDelegate:

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
        BackendAPIManager.sharedInstance.backgroundCompletionHandler = completionHandler
    }

Singleton:

import Alamofire

class BackendAPIManager: NSObject {
    static let sharedInstance = BackendAPIManager()

    var alamoFireManager : Alamofire.SessionManager!

    var backgroundCompletionHandler: (() -> Void)? {
        get {
            return alamoFireManager?.backgroundCompletionHandler
        }
        set {
            alamoFireManager?.backgroundCompletionHandler = newValue
        }
    }

    fileprivate override init()
    {
        let configuration = URLSessionConfiguration.background(withIdentifier: "com.url.background")
        configuration.timeoutIntervalForRequest = 200 // seconds
        configuration.timeoutIntervalForResource = 200
        self.alamoFireManager = Alamofire.SessionManager(configuration: configuration)
    }
}

Y las llamadas se hacen de la siguiente manera:

BackendAPIManager.sharedInstance.alamoFireManager.upload(multipartFormData: { (multipartFormData) in ...
 5
Author: Naloiko Eugene,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-08 13:59:38