Obtenga subyacente dispatch_queue_t desde NSOperationQueue

Parece que tengo cierta confusión entre las queues dispatch_queue_t y NSOperationQueue .

De forma pnetworkingeterminada, AFImageRequestOperation de AFImageRequestOperation ejecutará el bloque de callback de éxito en el hilo principal de la aplicación. Para cambiar esto, AFHTTPRequestOperation tiene la propiedad successCallbackQueue que le permite elegir en qué queue ejecutar la callback.

Estoy intentando ejecutar la callback de éxito en los mismos subprocesss de background / queue de background que ya hicieron la request HTTP. En lugar de volver al hilo principal, el NSOperationQueue que ejecutó la request HTTP debería ejecutar la callback también, ya que hay algunos cálculos pesados ​​que necesito hacer con algunas de las imágenes devueltas.

Mi primer bash fue establecer NSOperationQueue instancia NSOperationQueue en la que se ejecutaba AFImageRequestOperation . Sin embargo, la propiedad successCallbackQueue es de tipo dispatch_queue_t , así que necesito una manera de get el dispatch_queue_t subyacente de mi instancia de NSOperation , si existe tal cosa.

¿Es posible o necesito crear un dispatch_queue_t separado?

La razón por la que pregunto: Es algo extraño que AFNetworking henetworkinge de NSOperation , pero espera que usemos queues dispatch_queue_t para las devoluciones de llamada. Tipo de mezcla de los dos paradigmas dispatch_queue_t y NSOperationQueue .

Gracias por cualquier sugerencia!

No existe tal cosa, no hay una correspondencia uno a uno de un NSOperationQueue y un dispatch_queue_t , los conceptos de queue en las dos API son muy diferentes (por ejemplo, NSOperationQueue no tiene una queue FIFO estricta como lo hace GCD).

La única queue de despacho utilizada por NSOperationQueue para ejecutar su código es la queue concurrente global de prioridad pnetworkingeterminada.

NSOperationQueue no es su cuello de botella con AFNetworking. Las operaciones de request están vinculadas por la networking, no por la CPU o la memory. Todo el trabajo se realiza de forma asíncrona en las queues de envío, que son accesibles como properties en AFHTTPRequestOperation .

No es aconsejable usar el hilo de networking para realizar ningún procesamiento. Esto no mejorará el performance de ninguna manera.

En cambio, si observa problemas de performance, intente limitar el número máximo de operaciones simultáneas en la queue de operaciones, como una manera de controlar indirectamente la cantidad de trabajo que realizan esas queues de procesamiento de background.

Es interesante que AFHTTPClient utiliza un NSOperationQueue para ejecutar AFHTTPRequestOperations, pero GCD dispatch_queues para manejar los resultados.

Con respecto a NSOperationQueue, los documentos de Apple dicen:

Nota: En iOS 4 y versiones posteriores, las queues de operaciones usan Grand Central Dispatch para ejecutar operaciones.

pero no parece haber una API pública para get la dispatch_queue para una operación determinada.

Si no es tan importante para usted que la callback de éxito tiene que estar exactamente en la misma queue / subprocess que ejecutó la operación original, por qué no se establece:

 successCallbackQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0); 

XCode 6.4 para iOS 8.4, habilitado ARC

1) "… así que necesito una manera de get el dispatch_queue_t subyacente de mi instancia de NSOperation, si hay tal cosa".

Hay una propiedad de NSOperationQueue que puede ayudar:

 @property(assign) dispatch_queue_t underlyingQueue 

Se puede usar de la siguiente manera para asignar a NSOperationQueue:

 NSOperationQueue *concurrentQueueForServerCommunication = [[NSOperationQueue alloc] init]; dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); concurrentQueueForServerCommunication.underlyingQueue = concurrentQueue; 

O asigne desde NSOperationQueue:

 NSOperationQueue *concurrentQueueForServerCommunication = [[NSOperationQueue alloc] init]; dispatch_queue_t concurrentQueue = concurrentQueueForServerCommunication.underlyingQueue; 

No estoy seguro de si la API que está utilizando para la comunicación de networking actualiza su interfaz de usuario después de la finalización de la tarea de networking, pero en caso de que no lo haga, debe saber para volver a la queue principal cuando se ejecuta el bloque de finalización:

 dispatch_sync(dispatch_get_main_queue(), ^{ //Update your UI here... } 

¡Espero que esto ayude! Aclamaciones.

En primer lugar, es un buen comportamiento ejecutar el éxito de AFImageRequestOperation en el hilo principal porque el uso principal de esta operación es download una image en segundo plano y mostrarla en la interfaz de usuario (que debería estar en el hilo principal), pero para satisfacer las necesidades de aquellos usuarios (su caso también) que desean ejecutar la callback en otros subprocesss, también hay un successCalbackQueue.

Para que pueda crear su propio dispatch_queue_t con el método dispatch_queue_create o la forma recomendada, debe usar dispatch_get_global_queue para get la queue principal.

En cada caso, asegúrese de que en su bloque de éxito, si está haciendo algunos cambios a la interfaz de usuario, póngalos dentro de dispatch_async(dispatch_get_main_queue(), ^{ // main op here});

Código Swift 3, basado en la respuesta de @ serge-k:

 // Initialize the operation queue. let operationQueue = OperationQueue() operationQueue.name = "com.example.myOperationQueue" operationQueue.qualityOfService = .userInitiated // Initialize a backing DispatchQueue so we can reuse it for network operations. // Because no additional info is give, the dispatch queue will have the same QoS as the operation queue. let operationQueueUnderlyingQueue = DispatchQueue(label: "com.example.underlyingQueue") operationQueue.qualityOfService.underlyingQueue = operationQueueUnderlyingQueue 

A continuación, puede usar esto en Alamofire (o AFNetworking) de la siguiente manera:

 Alamofire.request("https://example.com/get", parameters: nil).validate().responseJSON(queue: operationQueue.underlyingQueue) { response in response handler code } 

Una advertencia aquí, de la documentation de Apple sobre cómo configurar la queue subyacente de OperationQueue :

El valor de esta propiedad solo se debe establecer si no hay operaciones en la queue; al establecer el valor de esta propiedad cuando operationCount no es igual a 0, se invalidArgumentException una invalidArgumentException . El valor de esta propiedad no debe ser el valor devuelto por dispatch_get_main_queue() . El nivel de calidad de service establecido para la queue de envío subyacente anula cualquier valor establecido para la propiedad qualityOfService la queue de qualityOfService .