Adición de retardo entre la ejecución de dos líneas siguientes


Necesito añadir retardo entre la ejecución de dos líneas en una(misma) función. ¿Hay alguna opción favorable para hacer esto?

Nota: No necesito dos funciones diferentes para hacer esto, y el retraso no debe afectar la ejecución de otras funciones.

Eg:

line 1: [executing first operation];

line 2: Delay                        /* I need to introduce delay here */

line 3: [executing second operation];

Cualquier ayuda es apreciable. Gracias de antemano...

Author: Hermann Klecker, 2013-03-11

6 answers

Puede usar gcd para hacer esto sin tener que crear otro método

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
  NSLog(@"Do some work");
});

Todavía debes preguntarte "¿realmente necesito agregar un retraso?", ya que a menudo puede complicar el código y causar condiciones de carrera

 170
Author: Paul.s,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-11 10:12:33

Puedes usar el método NSThread:

[NSThread sleepForTimeInterval: delay];

Sin embargo, si haces esto en el hilo principal, bloquearás la aplicación, por lo que solo hazlo en un hilo de fondo.


o en Swift

NSThread.sleepForTimeInterval(delay)

en Swift 3

Thread.sleep(forTimeInterval: delay)
 23
Author: Ashley Mills,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-18 10:36:36

Esta línea llama al selector secondMethod después de 3 segundos:

[self performSelector:@selector(secondMethod) withObject:nil afterDelay:3.0 ];

Utilícelo en su segunda operación con el retraso deseado. Si tiene mucho código, colóquelo en su propio método y llame a ese método con performSelector:. No bloqueará la interfaz de usuario como sleep

Edit: Si no desea un segundo método, puede agregar una categoría para poder usar bloques con performSelector:

@implementation NSObject (PerformBlockAfterDelay)

- (void)performBlock:(void (^)(void))block 
          afterDelay:(NSTimeInterval)delay
{
    block = [block copy];
    [self performSelector:@selector(fireBlockAfterDelay:) 
               withObject:block 
               afterDelay:delay];
}

- (void)fireBlockAfterDelay:(void (^)(void))block
{
    block();
}

@end

O tal vez incluso más limpio:

void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void))
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay),
      dispatch_get_current_queue(), block);
}
 17
Author: Sunkas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-18 06:09:15

Tengo un par de juegos por turnos en los que necesito que la IA haga una pausa antes de tomar su turno (y entre los pasos en su turno). Estoy seguro de que hay otras situaciones, más útiles, donde un retraso es la mejor solución. En Swift:

        let delay = 2.0 * Double(NSEC_PER_SEC) 
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay)) 
        dispatch_after(time, dispatch_get_main_queue()) { self.playerTapped(aiPlayView) }

Acabo de volver aquí para ver si las llamadas a Objective-C eran diferentes.(Tengo que añadir esto a ese, también.)

 8
Author: David Reich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-27 07:19:17

Si estás dirigido a iOS 4.0+, puedes hacer lo siguiente:

[executing first operation];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [executing second operation];
});
 3
Author: Attila H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-11 14:25:54

Como @Sunkas escribió, performSelector:withObject:afterDelay: es el pendiente de la dispatch_after solo que es más corto y tiene la sintaxis normal objective-c. Si necesita pasar argumentos al bloque que desea retrasar, simplemente puede pasarlos a través del parámetro withObject y lo recibirá en el selector que llame:

[self performSelector:@selector(testStringMethod:) 
           withObject:@"Test Test" 
           afterDelay:0.5];

- (void)testStringMethod:(NSString *)string{
    NSLog(@"string  >>> %@", string);
}

Si todavía desea elegir si lo ejecuta en el subproceso principal o en el subproceso actual, hay métodos específicos que le permiten especificar esto. La documentación de las manzanas dice esto:

Si desea que el mensaje se desque cuando el bucle de ejecución está en modo que no sea el modo predeterminado, utilice el performSelector:withObject:afterDelay: inModes: method instead. Si no está seguro de si el hilo actual es el hilo principal, puede utilice el performSelectorOnMainThread: withObject: waitUntilDone: o performSelectorOnMainThread: withObject: waitUntilDone: modes: method to garantice que su selector se ejecuta en el hilo principal. Para cancelar una en cola mensaje, utilice el cancelPreviousPerformRequestsWithtarget: o cancelPreviousPerformRequestsWithTarget: selector: object: method.

 0
Author: Alex Cio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-20 10:37:47