Descargar AlamoFire en session de background

Estoy usando Alamofire dentro de una nueva aplicación (Una muestra de Download Manager basada en Alamofire) Necesito algunas aclaraciones sobre la descarga de files usando la session de background. Necesito anular SessionDelegate para que funcione? ¿O solo backgroundCompletionHandler ?

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

Actualizar

Basado en este sorprendente tutorial , he creado un proyecto de ejemplo disponible en GitHub . Tiene un ejemplo para la gestión de la session en segundo plano.

De acuerdo con la Guía de progtwigció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 objects de configuration de background con los mismos identificadores que las sesiones que tenían tareas pendientes cuando la aplicación se ejecutó por última vez, y luego crear una session para cada uno de esos objects de configuration . Estas nuevas sesiones se reasocian de manera similar automáticamente con la actividad de background en curso.

Por lo tanto, aparentemente mediante el uso de las instancias de configuration de session de background adecuadas, sus descargas nunca estarán "en flujo".

También encontré esta respuesta realmente útil.

Respuesta original

Desde la página de GitHub de Alamofire:

Las aplicaciones pueden crear gerentes para sesiones de background y efímeras, así como nuevos gerentes que personalizan la configuration de session pnetworkingeterminada, como por ejemplo encabezados pnetworkingeterminados (HTTPAdditionalHeaders) o intervalo de time de espera (timeoutIntervalForRequest).

De forma pnetworkingeterminada, los methods de nivel superior utilizan una instancia de Manager compartido con configuration de session pnetworkingeterminada. Sin embargo, puede crear un administrador con configuration de session en segundo plano así:

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

A continuación, puede realizar requestes utilizando esta instancia del 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 } 

En realidad, es muy fácil con Alamofire:

1) su Alamofire.Manager debe configurarse con un identificador de session 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 la application(_:handleEventsForBackgroundURLSession:completionHandler: y pase el controller de finalización a Alamofire.SessionManager.backgroundCompletionHandler .

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

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

y mi administrador de networking tiene una propiedad computada como esta para configurar la propiedad Manager:

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

Estaba buscando la solución bastante time. Hasta leer el artículo mencionado anteriormente. El problema para mí fue: tuve que habilitar la comunicación de accesorios externos

introduzca la descripción de la imagen aquí

Todo lo demás se hizo como se describe arriba. AppDelegate:

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

Semifallo:

 import Alamofire class BackendAPIManager: NSObject { static let shanetworkingInstance = 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 realizan de la siguiente manera:

 BackendAPIManager.shanetworkingInstance.alamoFireManager.upload(multipartFormData: { (multipartFormData) in ...