Tengo un método que acepta un bloque y un bloque de finalización. El primer bloque debería ejecutarse en segundo plano, mientras que el bloque de finalización debería ejecutarse en cualquier cola a la que se haya llamado al método.
Para este último siempre lo usé dispatch_get_current_queue()
, pero parece que está obsoleto en iOS 6 o superior. ¿Qué debo usar en su lugar?
dispatch_get_current_queue()
está obsoleto en iOS 6? los doctores no dicen nada al respectoRespuestas:
El patrón de "ejecutar en cualquier cola en la que estuviera la persona que llama" es atractivo, pero en última instancia no es una gran idea. Esa cola podría ser una cola de baja prioridad, la cola principal o alguna otra cola con propiedades extrañas.
Mi enfoque favorito para esto es decir "el bloque de finalización se ejecuta en una cola definida por la implementación con estas propiedades: x, y, z", y dejar que el bloque se envíe a una cola en particular si la persona que llama quiere más control que eso. Un conjunto típico de propiedades para especificar sería algo así como "serial, no reentrante y asincrónico con respecto a cualquier otra cola visible de la aplicación".
** EDITAR **
Catfish_Man puso un ejemplo en los comentarios a continuación, solo lo estoy agregando a su respuesta.
fuente
Este es fundamentalmente el enfoque incorrecto para la API que está describiendo. Si una API acepta un bloque y un bloque de finalización para ejecutarse, los siguientes hechos deben ser ciertos:
El "bloque para ejecutar" debe ejecutarse en una cola interna, por ejemplo, una cola que es privada para la API y, por lo tanto, está completamente bajo el control de esa API. La única excepción a esto es si la API declara específicamente que el bloque se ejecutará en la cola principal o en una de las colas simultáneas globales.
El bloque de finalización siempre debe expresarse como una tupla (cola, bloque) a menos que se cumplan las mismas suposiciones que para el n. ° 1, por ejemplo, el bloque de finalización se ejecutará en una cola global conocida. Además, el bloque de finalización debe enviarse de forma asíncrona en la cola pasada.
Estos no son solo puntos estilísticos, son completamente necesarios si su API va a estar a salvo de interbloqueos u otros comportamientos de casos extremos que, de lo contrario, lo colgarán del árbol más cercano algún día. :-)
fuente
Las otras respuestas son geniales, pero para mí la respuesta es estructural. Tengo un método como este que está en un Singleton:
que tiene dos dependencias, que son:
y
De esa manera, centralizo mis llamadas para enviarlas en el otro hilo.
fuente
Debe tener cuidado con el uso de
dispatch_get_current_queue
en primer lugar. Desde el archivo de encabezado:Puede hacer una de estas dos cosas:
Mantenga una referencia a la cola en la que publicó originalmente (si la creó a través de
dispatch_queue_create
) y úsela a partir de ese momento.Utilice las colas definidas por el sistema a través de
dispatch_get_global_queue
y lleve un registro de cuál está utilizando.Efectivamente, mientras confiaba anteriormente en el sistema para realizar un seguimiento de la cola en la que se encuentra, tendrá que hacerlo usted mismo.
fuente
dispatch_get_current_queue()
para averiguar qué cola es? A veces, el código que necesita saber en qué cola se está ejecutando no tiene ningún control o conocimiento de ello. Tengo una gran cantidad de código que puede (y debe) ejecutarse en una cola en segundo plano, pero ocasionalmente necesito actualizar la interfaz gráfica de usuario (barra de progreso, etc.) y, por lo tanto, necesito dispatch_sync () a la cola principal para esas operaciones. Si ya está en la cola principal, dispatch_sync () se bloqueará para siempre. Me llevará meses refactorizar mi código para esto.Apple se había desaprobado
dispatch_get_current_queue()
, pero dejó un agujero en otro lugar, por lo que aún podemos obtener la cola de envío actual:Esto funciona al menos para la cola principal. Tenga en cuenta que
underlyingQueue
propiedad está disponible desde iOS 8.Si necesita realizar el bloque de finalización en la cola original, también puede usarlo
OperationQueue
directamente, es decir, sin GCD.fuente
Para aquellos que todavía necesitan comparar en cola, puede comparar las colas por su etiqueta o especificaciones. Consulte esto https://stackoverflow.com/a/23220741/1531141
fuente
Esta es una respuesta yo también. Entonces hablaré sobre nuestro caso de uso.
Tenemos una capa de servicios y la capa de UI (entre otras capas). La capa de servicios ejecuta tareas en segundo plano. (Tareas de manipulación de datos, tareas CoreData, llamadas de red, etc.). La capa de servicio tiene un par de colas de operaciones para satisfacer las necesidades de la capa de interfaz de usuario.
La capa de interfaz de usuario se basa en la capa de servicios para hacer su trabajo y luego ejecutar un bloque de finalización satisfactoria. Este bloque puede tener código UIKit. Un caso de uso simple es obtener todos los mensajes del servidor y volver a cargar la vista de colección.
Aquí garantizamos que los bloques que se pasan a la capa de servicios se envían en la cola en la que se invocó el servicio. Dado que dispatch_get_current_queue es un método obsoleto, usamos NSOperationQueue.currentQueue para obtener la cola actual de la persona que llama. Nota importante sobre esta propiedad.
Dado que siempre invocamos nuestros servicios en una cola conocida (nuestras colas personalizadas y cola principal), esto funciona bien para nosotros. Tenemos casos en los que el servicio A puede llamar al servicio B que puede llamar al servicio C. Dado que controlamos desde dónde se realiza la primera llamada de servicio, sabemos que el resto de los servicios seguirán las mismas reglas.
Entonces NSOperationQueue.currentQueue siempre devolverá una de nuestras Queues o MainQueue.
fuente