Comprobación de múltiples respuestas asincrónicas de Alamofire y Swift

Estoy escribiendo una aplicación que depende de los datos de varios sitios / servicios, e implica la realización de cálculos basados ​​en datos de estas diferentes fonts para producir un producto final.

He escrito una clase de ejemplo con dos funciones a continuación que reúne datos de las dos fonts. He elegido hacer las funciones diferentes, porque a veces aplicamos diferentes métodos de autenticación dependiendo de la fuente, pero en este ejemplo acabo de desglosarlos en su forma más simple. Ambas funciones usan Alamofire para disparar y manejar las solicitudes.

Luego tengo una función de inicialización, que dice que si hemos recostackdo datos de ambas fonts, luego cargamos otro archivo de punta, de lo contrario esperamos por unos segundos, si no se ha devuelto ninguna respuesta, luego cargamos un archivo de punta de error del servidor.

Intenté hacer este ejemplo lo más simple posible. Esencialmente. Este es el tipo de lógica que me gustaría seguir. Lamentablemente, parece que esto no funciona actualmente en su implementación actual.

import Foundation class GrabData{ var data_source_1:String? var data_source_2:String? init(){ // get data from source 1 get_data_1{ data_source_1 in println("\(data_source_1)") } // get data from source 2 get_data_2{ data_source_1 in println("\(data_source_1)") } var timer = 0; while(timer ()) -> () { if let datasource1 = self.data_source_1{ completionHandler(datasource1) }else{ var url = "http://somewebsite.com" Manager.sharedInstance.request(.GET, url).responseString { (request, response, returnedstring, error) in println("getting data from source 1") let datasource1 = returnedstring self.data_source_1 = datasource1 completionHandler(datasource1!) } } } func get_data_2(completionHandler: (String) -> ()) -> () { if let datasource2 = self.data_source_2{ completionHandler(datasource2) }else{ var url = "http://anotherwebsite.com" Manager.sharedInstance.request(.GET, url).responseString { (request, response, returnedstring, error) in println("getting data from source 2") let datasource2 = returnedstring self.data_source_2 = datasource2 completionHandler(datasource2!) } } } } 

Sé que podría poner el segundo cierre dentro del primero dentro de la función init, sin embargo, no creo que esta sea la mejor práctica y en realidad estoy sacando de más de 2 fonts, por lo que el cierre sería n cierres profundos.

Cualquier ayuda para encontrar la mejor manera de verificar si múltiples fonts de datos dieron una respuesta válida, y sería muy apreciado manejarla adecuadamente.

Mejor que ese proceso de bucle, que bloquearía el hilo, podría usar el grupo de envío para realizar un seguimiento de cuándo se realizaron las solicitudes. Así que “ingrese” al grupo antes de emitir cada una de las solicitudes, “abandone” el grupo cuando se realiza la solicitud, y configure un locking / cierre de “notificación” al que se llamará cuando finalicen todas las tareas del grupo.

Por ejemplo, en Swift 3:

 let group = DispatchGroup() group.enter() retrieveDataFromURL(url1, parameters: firstParameters) { group.leave() } group.enter() retrieveDataFromURL(url2, parameters: secondParameters) { group.leave() } group.notify(queue: .main) { print("both requests done") } 

O, en Swift 2:

 let group = dispatch_group_create() dispatch_group_enter(group) retrieveDataFromURL(url1, parameters: firstParameters) { dispatch_group_leave(group) } dispatch_group_enter(group) retrieveDataFromURL(url2, parameters: secondParameters) { dispatch_group_leave(group) } dispatch_group_notify(group, dispatch_get_main_queue()) { print("both requests done") } 

El otro enfoque es envolver estas solicitudes dentro de una subclase asíncrona NSOperation (haciéndolas cancelables, que le dan control sobre limitar el grado de concurrencia, etc.), pero eso es más complicado, por lo que puede comenzar con grupos de despacho como se muestra arriba.