2011-08-17 13 views
16

Necesito una forma segura de decir: "iOS, quiero que este método se ejecute a.s.a.p., pero NO en ESTE ciclo iteración. Lo antes posible en el próximo, pero no en este. Gracias".Cómo llamar a un método a.s.a.p. pero a la primera en la próxima iteración de bucle de ejecución?

En este momento Siempre estoy haciendo de esta manera:

[self performSelector:@selector(doSomethingInNextRunLoop) withObject:nil afterDelay:0]; 
[self doSomeOtherThings]; 

Con la suposición de que -doSomeOtherThings siempre se lleva a cabo antes -doSomethingInNextRunLoop.

La documentación dice:

Especificación de un retardo de 0 no necesariamente causa el selector sea realiza inmediatamente. El selector todavía está en cola en el ciclo de ejecución de la secuencia y se realiza tan pronto como sea posible.

Así que, básicamente, puede suceder que el método es llamado inmediatamente como si acabara enviado un mensaje directo, causando -doSomethingInNextRunLoop que se ejecutarán antes -doSomeOtherThings?

¿Cómo puedo estar absolutamente seguro de que se llamará a.s.a.p. pero NUNCA en esta misma iteración de bucle de ejecución?

Para aclarar la redacción: Con run loop me refiero al hilo principal, y la iteración en la que todos los métodos deben retornar hasta que el hilo esté listo de nuevo para los nuevos eventos.

Respuesta

9

Si le preocupa que Apple pueda algún día un caso especial un retraso de 0, siempre puede especificar un retraso de 1e-37 más o menos. Aunque la documentación para performSelector:withObject:afterDelay: se puede leer fácilmente para garantizar que el selector esté siempre programado para la siguiente iteración del ciclo de ejecución.

Si le preocupa que Apple algún día un caso especial retrase menos de un límite inferior arbitrario, siempre puede intentar usar NSRunLoop's performSelector:target:argument:order:modes: que la documentación especifica que programará la ejecución para la próxima iteración del ciclo de ejecución.

+0

¡Magnífico! Una categoría para facilitar esto tendría sentido. – openfrog

0

Seguramente usted acaba de hacer esto;

[self doSomeOtherThings]; 
[self performSelector:@selector(doSomethingInNextRunLoop) withObject:nil afterDelay:0]; 

Lo que garantiza el orden de ejecución que desea.

+1

No siempre es conveniente (o posible) para reorganizar el código de esa manera en los casos más complejos que este ejemplo trivial utilizado para ilustración. – Anomie

+0

No realmente. Hay buenas razones para realizar cosas en la iteración de ciclo de ejecución NEXT. Uno de ellos: dejar que la interfaz de usuario se actualice entre ellos. Mejorando el rendimiento percibido. Entre muchos otros. Además de eso, Anomie tiene razón. – openfrog

+0

Por supuesto, la respuesta de Anomie da en el clavo, solo estoy señalando que en algunos casos, la reorganización del código también puede resolver el problema. Un poco como el bloque de escritores, a veces los desarrolladores se obsesionan con la resolución de un problema de una manera particular cuando de hecho hay un plan lateral B. FWIW No conozco NINGUNA instancia donde el estándar performSelector: withObject: afterDelay: 0 da como resultado bloquear y utilizar la técnica con frecuencia para optimizar el código de UI escrito por otros. – Roger

1

Creo que la conclusión de la lectura de la documentación es incorrecta.

Así que, básicamente, puede suceder que el método es llamado inmediatamente como si acabara enviado un mensaje directo

No. La parte de la documentación que cita dice que el selector siempre se pone en cola en el ejecutar bucle, no importa qué. Por lo tanto, nunca se ejecutará solo como un mensaje directo.

La primera frase con "no necesariamente" podría ser un poco engañosa, pero creo que la segunda oración realmente debería aclarar que lo que temes no va a suceder.

+0

Esperemos que tenga razón, porque apuesto a que mucha gente depende de que esté en cola para la próxima iteración. Aún así, hay algo de incertidumbre. – openfrog

6

bastante trivial usando GCD (Grand Central Dispatch):

dispatch_async (dispatch_get_main_queue(), ^{ 
    NSLog (@"This stuff runs in the next iteration of the main run loop"); 
}); 
Cuestiones relacionadas