¿Cómo puedo especificar los types de devolución en bloques GCD?

¿Cómo puedo especificar los types de devolución en bloques GCD? Aquí quiero devolver mi resultado como NSData

 - (NSData *)returnData:(NSString *)urlString{ dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(concurrentQueue, ^{ // here return type showing error NSString *strUrl = urlString; if([strUrl length] == 0) return nil; // from this point i want to stop the execution of the block and return nil . // otherwise only continue the left operations }); } 

 - (NSData *)returnData:(NSString *)urlString { dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // Declare your local data outside the block. // `__block` specifies that the variable can be modified from within the block. __block NSData *localData = nil; dispatch_sync(concurrentQueue, ^{ // Do something with `localData`... localData = somethingWonderful; }); // `localData` now contains your wonderful data. return localData; } 

El formatting del bloque (parameters / tipo de retorno) se especifica en la firma de la function. En este caso, dispatch_sync usa un bloque sin tipo de retorno y sin parameters. Si desea que funcionen otras variables, debe declararlas fuera del bloque, como en el código anterior.

Dado que un bloque comparte el scope con el padre, es más fácil no especificar un tipo de retorno. Por ejemplo:

 - (NSData *)returnData:(NSString *)urlString{ dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); __block NSData *data; // the __block keyword allows this variable to be changed by a block dispatch_sync(concurrentQueue, ^(NSData *)){ // here return type showing error data = [NSData dataWithContentsOfURL:@"http://stackoverflow.com"]; }); return data; } 

Si desea especificar un tipo de retorno, entonces no puede usar dispatch_sync() , ya que solo acepta bloques sin tipo de retorno. Un ejemplo de cómo usar bloques manualmente es:

 typedef NSData *(^MyDataBlock)(); MyDataBlock getData = ^ NSData *() { return [NSData data]; }; NSData *data = getData(); 

Tenga en count que debido a que no está utilizando dispatch_sync() en el segundo ejemplo, este código se ejecutará inmediatamente en la queue actual en lugar de esperar hasta que haya un time de CPU disponible. Esperar que la CPU tenga un time de inactividad puede ser realmente más rápido que ejecutarlo de inmediato.

La ventaja es que este enfoque es mucho más flexible, puede pasar la variable getData a otros methods y así sucesivamente, e incluso podría ejecutarlo dentro de su propia llamada dispatch_sync() para aprovechar el sistema prioritario de GCD.

¿Cuál es el error exacto que estás viendo? Porque esta linea

 dispatch_sync(concurrentQueue, ^(NSData *)){ // here return type showing error 

tiene un error de syntax. Tienes un callejón sin salida ) después de tu list de arguments en bloque.

Incluso si arreglas eso, tienes otro problema, que es que estás intentando devolver un valor de un bloque pasado a dispatch_sync() , y sin embargo, dispatch_sync() espera un bloque que devuelve void . Parece que lo que realmente intentas hacer es devolver los datos de la function, pero para hacerlo debes transferir los datos del bloque a tu function exterior. Puede hacer esto con una variable __block -qualified, como esta:

 - (NSData *)returnData:(NSString *)urlString{ dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); __block NSData *localData = nil; dispatch_sync(concurrentQueue, ^{ if ([urlString length] == 0) { // we don't have any data to return return; // localData is already nil } // calculate localData localData = ...; }); // Now localData should be populated return localData; } 

Para ampliar la precaución de Frioze: si llama a cualquier API no recomendada para usar en el hilo principal de la queue a la que no sincroniza, y llama a dispatch_sync desde el hilo principal, es posible que haya llamado a esa API desde el hilo principal como lo ha hecho Pedimos esperar a que se complete. Esto es cierto no solo para el bloque en su llamada _sincrónica, sino también para los bloques anteriores enviados a través de _async que aún no se han completado.