2012-10-12 104 views
5

Necesito retrasar durante un cierto período de tiempo y, sin embargo, permitir que otras cosas en el mismo ciclo de ejecución sigan funcionando. He estado usando el siguiente código para hacer esto:Forma correcta de retrasar al permitir que el ciclo de ejecución continúe

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; 

Esto parece hacer exactamente lo que yo quiero, excepto que a veces la función devuelve inmediatamente sin esperar el tiempo deseado (1 segundo).

¿Alguien me puede decir qué podría causar esto? ¿Y cuál es la forma correcta de esperar mientras se permite ejecutar el ciclo de ejecución?

NOTA: Deseo retrasar de manera similar a sleep(), de modo que después de la demora vuelva al mismo flujo de ejecución que antes.

+0

¿Qué es lo que desea retrasar? ¿Has mirado 'dispatch_after'? –

+0

Quiero retrasar el hilo actual, de una manera similar a sleep(), excepto que quiero que el runloop continúe ejecutándose (para que otros eventos y cosas puedan activarse) durante ese tiempo de retraso. – Locksleyu

Respuesta

8

Debe usar GCD y dispatch_after para eso. Es mucho más reciente y eficiente (y seguro para subprocesos y todo), y muy fácil de usar.

Hay incluso un fragmento de código incrustado en Xcode, de manera que si comienza a escribir dispatch_after se le sugerirá el fragmento y si se valida que escribirá los preparados 2-3 líneas para que en su código :)

Code Snippet suggestion by Xcode

int64_t delayInSeconds = 2.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    <#code to be executed on the main queue after delay#> 
}); 
+1

El método que menciona ejecuta una pieza diferente de código en la cola principal, lo que quiero hacer es básicamente retrasar durante un período de tiempo y volver al código que estaba ejecutando antes. Por ejemplo, si tuviera un bucle for que hiciera una impresión, espere un segundo y luego repita. Quiero que la declaración simplemente 'duerma' por un segundo y luego regrese al bucle for que estaba ejecutando antes. ¿Tiene sentido? – Locksleyu

+1

Eso tiene y no tiene sentido. Puedes hacer esto haciendo que tu hilo duerma ('[NSThread sleepForTimeinterval:]' o 'usleep()'?) Pero esto hará una pausa activa, que no se recomienda en los patrones de programación OOP correctos. Y si ejecuta su bucle for en el runloop principal, por supuesto, "congelará" su aplicación. Entonces, probablemente sea un mal diseño. – AliSoftware

+2

La solución que veo si realmente quieres ejecutar N iteraciones separadas por 1 segundo es 'for (int i = 0; i AliSoftware

1

Use un NSTimer para iniciar una llamada a algún método después de un cierto retraso.

1

The accepted SO answer here debería ayudar. También puede implementar dispatch_afer de David (explained here), que es una forma más actualizada de hacer lo mismo, usando GCD.

Existen varias funciones de GCD como esta que vale la pena conocer, y son muy fáciles de usar.

+0

Gracias por la respuesta. Esto no es exactamente lo que estoy buscando sin embargo (lo siento si no estaba claro en la publicación). Quiero básicamente bloquear mi hilo actual (similar a un sueño (1)) y luego devolver el control a donde estaba antes. El código al que vinculó ejecuta "algún otro código" después de un período de tiempo, en lugar de solo devolver el control a mi hilo para que pueda continuar donde lo dejé. El ejemplo que di hace esto, pero a veces no se puede retrasar correctamente. – Locksleyu

0

Ha intentado performSelector:withObject:afterDelay:?

Desde el Apple documentation

invoca un método del receptor en el subproceso actual utilizando el modo por defecto después de un retardo.

0

Tuve un problema similar y esta es mi solución. Espero que funcione para otros también.

__block bool dispatched = false; 
while (put your loop condition here) 
{ 
    if (dispatched) 
    { 
     // We want to relinquish control if we are already dispatched on this iteration. 
     [ [ NSRunLoop currentRunLoop ] runMode: NSDefaultRunLoopMode beforeDate:[ NSDate date ] ]; 
     continue; 
    } 

    // mark that a dispatch is being scheduled 
    dispatched = true; 

    int64_t delayInNanoSeconds = (int64_t) (0.1 * (float) NSEC_PER_SEC); 
    dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, delayInNanoSeconds); 

    dispatch_after(delayTime, dispatch_get_main_queue(), ^() { 
     // Do your loop stuff here 
     // and now ready for the next dispatch 
     dispatched = false; 
    }); 
} // end of while 
Cuestiones relacionadas