objective c - Agregar retraso entre la ejecución de dos líneas siguientes
objective-c delay (6)
Al igual que @Sunkas escribió, performSelector:withObject:afterDelay:
es el colgante para el dispatch_after
solo que es más corto y tiene la sintaxis performSelector:withObject:afterDelay:
objective-c
normal. Si necesita pasar argumentos al bloque que desea retrasar, puede pasarlos a través del parámetro withObject
y lo recibirá en el selector
que llama:
[self performSelector:@selector(testStringMethod:)
withObject:@"Test Test"
afterDelay:0.5];
- (void)testStringMethod:(NSString *)string{
NSLog(@"string >>> %@", string);
}
Si aún desea elegir usted mismo si lo ejecuta en el hilo principal o en el hilo actual, existen métodos específicos que le permiten especificarlo. La documentación de las manzanas dice esto:
Si desea que el mensaje se elimine de la cola cuando el ciclo de ejecución está en un modo distinto al predeterminado, utilice el método performSelector: withObject: afterDelay: inModes: en su lugar. Si no está seguro de si el hilo actual es el hilo principal, puede usar el método performSelectorOnMainThread: withObject: waitUntilDone: o performSelectorOnMainThread: withObject: waitUntilDone: modes: para garantizar que su selector se ejecuta en el hilo principal. Para cancelar un mensaje en cola, use el método cancelPreviousPerformRequestsWithTarget: o cancelPreviousPerformRequestsWithTarget: selector: object :.
Necesito agregar retraso 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 la demora no debe afectar la ejecución de otras funciones.
p.ej:
line 1: [executing first operation];
line 2: Delay /* I need to introduce delay here */
line 3: [executing second operation];
Cualquier ayuda es apreciable. Gracias por adelantado...
Esta línea llama al selector secondMethod después de 3 segundos:
[self performSelector:@selector(secondMethod) withObject:nil afterDelay:3.0 ];
Úselo en su segunda operación con su 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 el sleep
Editar: 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 quizás 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);
}
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");
});
Debería preguntarse "realmente necesito agregar un retraso", ya que a menudo puede complicar el código y causar condiciones de carrera.
Puedes usar el método NSThread
:
[NSThread sleepForTimeInterval: delay];
Sin embargo, si haces esto en el hilo principal, bloquearás la aplicación, así que solo haz esto en un hilo de fondo.
o en Swift
NSThread.sleepForTimeInterval(delay)
en Swift 3
Thread.sleep(forTimeInterval: delay)
Si se dirige a iOS 4.0 o posterior, puede 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];
});
Tengo un par de juegos por turnos en los que necesito que la inteligencia artificial se detenga antes de tomar su turno (y entre los pasos en su turno). Estoy seguro de que hay otras situaciones más útiles en las que una demora 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 de Objective-C eran diferentes. (Necesito agregar esto a eso también).