como activar iphone ios objective-c grand-central-dispatch dispatch

nfc iphone 7 como activar



Obtener cola de despacho actual? (7)

Como un enfoque alternativo a este método de performSelector:withObject:afterDelay: distribuye la llamada en el ciclo de ejecución del subproceso actual. De acuerdo con los documentos:

Este método configura un temporizador para realizar el mensaje aSelector en el ciclo de ejecución del subproceso actual.

Obviamente sugiero usar esto con un retraso de cero, que, según los documentos, nuevamente:

Especificar un retraso de 0 no necesariamente hace que el selector se realice de inmediato. El selector todavía está en cola en el ciclo de ejecución del subproceso y se realiza lo antes posible.

Lamentablemente, requiere exactamente un argumento, por lo que algunas soluciones pueden ser necesarias si su método requiere más o menos.

Otra cosa que noté es que este método no está disponible para protocolos, sino solo implementaciones. Esto se debe a que este método vive en una categoría de objeto NSObject , y no en la interfaz NSObject (ver PS a continuación). Esto se puede solucionar fácilmente lanzando a id .

PD: existen dos NSObject diferentes, un protocolo y una implementación. Observe la declaración de NSObject :

@interface NSObject <NSObject> { ... }

Puede parecer extraño, pero uno está siendo declarado (después de @interface ) y el otro es un protocolo previamente declarado (entre < y > ). Cuando se declara un protocolo que amplía NSObject (es decir, @protocol Foo <NSObject> ), el protocolo hereda los métodos del último, pero no del anterior. Eventualmente, el protocolo es implementado por alguna clase que hereda de la implementación de NSObject , por lo que todas las instancias NSObject implementación de NSObject aún se mantienen. Pero me estoy saliendo del tema.

Tengo un método que debe ser compatible con ser llamado desde cualquier cola, y debe esperar. Ejecuta un código en un subproceso en segundo plano, y luego usa dispatch_get_main_queue cuando devuelve un valor a su argumento de bloque. No quiero que forzar a la cola principal si no fue cuando entró en el método. ¿Hay alguna manera de obtener un puntero a la cola de despacho actual?


Con la desactivación de dispatch_get_current_queue() efectivamente no hay forma de saber en qué cola está ejecutando. Si examina detenidamente las fuentes de GCD , eventualmente verá que esto se debe a que puede haber varias respuestas a la pregunta "¿en qué cola me estoy ejecutando?" (Debido a que las colas finalmente se dirigen a una de las colas globales, etc.)

Si desea garantizar que un bloque futuro se ejecute en una cola específica, la única forma es hacer que su API acepte una cola como parámetro junto con el bloque de finalización. Esto permite que la persona que llama decida dónde se ejecuta la finalización.

Si simplemente es suficiente saber si la persona que llama está en el hilo principal o no, puede usar +[NSThread isMainThread] para averiguarlo. En el caso común, todos los bloques que se ejecutan en la cola principal de GCD se ejecutarán en el hilo principal. (Una excepción a esta regla es si su aplicación usa dispatch_main() en lugar de un ciclo de ejecución principal, tendrá que usar dispatch_get_specific y amigos para detectar con certeza que está ejecutando en la cola principal; esta es una circunstancia comparativamente rara .) Más comúnmente, tenga en cuenta que no todo el código que se ejecuta en el hilo principal se ejecuta en la cola principal a través de GCD; GCD está subordinado al thread runloop principal. Para su caso específico, parece que eso podría ser suficiente.


Con la desactivación de dispatch_get_current_queue() no puede obtener directamente un puntero a la cola en la que se está ejecutando, sin embargo , puede obtener la etiqueta de la cola actual llamando a dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) y eso le brinda cierta flexibilidad.

Siempre puede verificar si está en esa fila específica simplemente comparando sus etiquetas, por lo que en su caso, si no desea forzarla en la cola principal, cuando ingresó el método, puede utilizar la siguiente marca:

let isOnMainQueue = (dispatch_queue_get_label(dispatch_get_main_queue()) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL))

Si se está ejecutando en la cola global, respetuosamente obtendrá la etiqueta de la cola asociada con su tipo de QOS, que puede ser una de las siguientes:

com.apple.root.user-interactive-qos //qos_class_t(rawValue: 33) com.apple.root.user-initiated-qos //qos_class_t(rawValue: 25) com.apple.root.default-qos //qos_class_t(rawValue: 21) com.apple.root.utility-qos //qos_class_t(rawValue: 17) com.apple.root.background-qos //qos_class_t(rawValue: 9)

Y luego puede usar dispatch_get_global_queue(qos_class_self(), 0) que le devolverá la misma cola global en la que se está ejecutando.

Pero creo que Apple en particular nos desalienta a limitar la lógica a la cola a la que nos llamaron, así que mejor utilizar esto para fines exclusivamente de depuración.


De hecho, todavía hay una manera de comparar la cola.

Cuando configure su cola, asegúrese de agregar la etiqueta. Para mis propósitos, tengo una cola compartida que se utiliza para acceder a una base de datos para evitar el bloqueo de la base de datos. En mi archivo DB.m he definido la función de cola compartida como:

const char *kTransactionQueueLabel = "DB_TRANSACTION_DISPATCH_QUEUE"; + (dispatch_queue_t)sharedDBTransactionQueue { static dispatch_queue_t sharedDBQueue = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedDBQueue = dispatch_queue_create(kTransactionQueueLabel, DISPATCH_QUEUE_SERIAL); }); return sharedDBQueue; }

La cola de transacciones de db compartida se usa localmente en el archivo para enviar todas las ejecuciones a la base de datos. Sin embargo, también hay un acceso público para permitir el envío de transacciones completas a la base de datos. Entonces, internamente, si se llama a un método de acceso DB desde la cola de transacciones, necesitamos despachar internamente en una cola diferente (todos los despachos síncronos). Así que internamente, siempre envío en la cola adecuada usando el getter a continuación.

/** * @description Decide which queue to use - if we are already in a transaction, use the internal access queue, otherwise use the shared transaction queue. */ - (dispatch_queue_t)getProperQueueForExecution { const char *currentLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL); dispatch_queue_t sharedAccessQueue = [DB sharedDBTransactionQueue]; if (strcmp(currentLabel, kTransactionQueueLabel) == 0) { sharedAccessQueue = [DB sharedInternalDBAccessQueue]; } return sharedAccessQueue; }

Espero que esto ayude. Perdón por el largo ejemplo. La esencia de esto es que puedes usar

const char *currentLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);

para obtener la etiqueta de la cola actual y compararla con una etiqueta definida.


Puedes usar NSOperationQueue para eso. NSOperationQueue tiene la función de clase [NSOperationQueue currentQueue] , que devuelve la cola actual como un objeto NSOperationQueue. Para obtener el objeto de cola de despacho, puede usar [NSOperationQueue currentQueue].underlyingQueue , que devuelve su cola actual como dispatch_queue_t .

Swift 3:

if let currentDispatch = OperationQueue.current?.underlyingQueue { print(currentDispatch) }

- funciona para la cola principal!


Tengo los mismos requisitos funcionales que menciona la publicación original. Debería poder llamar a esta función asíncrona en cualquier cola, pero si se llama a la cola principal, se devuelve una llamada al usuario en la cola principal. Simplemente lo manejo así:

// cache value for if we should callback on main queue BOOL callbackOnMT = [NSThread isMainThread]; // ... // ... do async work... // ... if (callbackOnMT && ![NSThread isMainThread]){ dispatch_async(dispatch_get_main_queue(), ^{ // callback to user on main queue // as they called this function on main queue callbackToUser(); }); } else{ // callback to user on our current queue // as they called this function on a non-main queue callbackToUser(); }