Comprobación de múltiples respuestas asíncronas de Alamofire y Swift

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

He escrito una class de ejemplo con dos funciones a continuación que recostack datos de las dos fonts. He elegido hacer las funciones diferentes, porque a veces aplicamos diferentes methods de authentication dependiendo de la fuente, pero en este ejemplo acabo de eliminarlos a su forma más simple. Ambas funciones utilizan Alamofire para disparar y manejar las requestes.

Luego tengo una function de initialization, que dice que si hemos recostackdo correctamente los datos de ambas fonts, entonces carguemos otro file de nib; de lo contrario, esperamos hasta por segundos, si no se ha devuelto ninguna respuesta, entonces carguemos un file de nib de error del server.

He tratado de hacer que este ejemplo sea 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<5){ if((data_source_1 == nil) && (data_source_2 == nil)){ // do nothing unless 4 seconds has elapsed if (timer == 4){ // load server error nib } }else{ // load another nib, and start manipulating data } // sleep for 1 second sleep(1) timer = timer+1 } } func get_data_1(completionHandler: (String) -> ()) -> () { if let datasource1 = self.data_source_1{ completionHandler(datasource1) }else{ var url = "http://somewebsite.com" Manager.shanetworkingInstance.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.shanetworkingInstance.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 pude poner el segundo cierre dentro del primero dentro de la function init, sin embargo, no creo que esta sea una práctica recomendada y de hecho estoy tirando de más de 2 fonts, por lo que el cierre sería n cierres profundos.

Cualquier ayuda para descubrir la mejor manera de verificar si varias fonts de datos ofrecían una respuesta válida, y el manejo apropiado sería muy apreciado.

Mejor que ese process 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 requestes. Por lo tanto, "ingrese" al grupo antes de emitir cada una de las requestes, "deje" al grupo cuando finalice la request y configure un bloque / cierre "notificar" que se llamará cuando se realicen 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 requestes dentro de una subclass NSOperation asíncrona (haciéndolas cancelables, dándote el control de restringir el grado de concurrency, etc.), pero eso es más complicado, por lo que podrías comenzar con los grupos de envío como se muestra arriba.