iOS: no regrese de la function hasta que se completen varios subprocesss de background

Esto parece ser realmente simple, pero estoy teniendo muchos problemas. Tengo una function que dispara un montón de otras funciones que se ejecutan en segundo plano y tienen bloques de finalización. Quiero que mi function espere hasta que se hayan llamado todos los bloques de finalización antes de que regrese.

No tengo control de la function que estoy llamando que se ejecuta en segundo plano. De lo contrario, simplemente lo modificaría para usar dispatch_async con mi propia queue y luego esperar en esa queue para terminar.

Ejemplo de cómo se ve mi situación:

- (void)functionThatShouldBeSynchronous { for (int i = 0; i < 10; i++) { [self doSomethingInBackground:^{ NSLog(@"completed!"); }]; } // How do I wait until all 10 threads have completed before returning? } - (void)doSomethingInBackground:(void(^)())completion { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ [NSThread sleepForTimeInterval:1.0f]; // Do stuff completion(); // Execute completion block }); } 

Gracias por adelantado.

Use un grupo de envío como este:

 - (void)functionThatShouldBeSynchronous { dispatch_group_t taskGroup = dispatch_group_create(); for (int i = 0; i < 10; i++) { dispatch_group_enter(taskGroup); [self doSomethingInBackground:^{ NSLog(@"completed!"); dispatch_group_leave(taskGroup); }]; } // Waiting for threads dispatch_group_wait(taskGroup, DISPATCH_TIME_FOREVER); dispatch_release(taskGroup); // Background work complete } 

Si desea un time de espera en espera de los subprocesss, puede cambiar la línea dispatch_group_wait a este

 // Waiting 10 seconds before giving up if (dispatch_group_wait(taskGroup, dispatch_time(DISPATCH_TIME_NOW, 10000000000)) != 0) { // Timeout } 

El parámetro está en nanosegundos.

Como dicen, no debes bloquear el hilo principal. En ese caso, podrías hacerlo así:

 typedef void(^MyCompletionHandler)(); -(void)functionDoingBackgroundWorkWithCompletionHandler:(MyCompletionHandler)completionHandler { dispatch_group_t taskGroup = dispatch_group_create(); for (int i = 0; i < 10; i++) { dispatch_group_enter(taskGroup); [self doSomethingInBackground:^{ NSLog(@"completed!"); dispatch_group_leave(taskGroup); }]; } dispatch_queue_t waitingQueue = dispatch_queue_create("com.mycompany.myapp.waitingQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(waitingQueue, ^{ // Waiting for threads dispatch_group_wait(taskGroup, DISPATCH_TIME_FOREVER); dispatch_release(taskGroup); // Background work complete dispatch_async(dispatch_get_main_queue(), ^{ // Calling the completion handler on the main thread (If you like) completionHandler(); }); dispatch_release(waitingQueue); }); }