2011-05-13 17 views
33

Así que estoy desarrollando mi primera aplicación iOS y necesito ayuda ...Xcode Objective-C | iOS: ¿función de retraso/ayuda de NSTimer?

Programa simple por ahora, tengo alrededor de 9 botones y cuando presiono el primer botón, o cualquier botón, solo quiero el primer botón para resalte durante 60 milisegundos, unhighlight, resaltados del segundo botón, espere 60 milisegundos, no ilumine y así sucesivamente para el resto de los botones para que parezca un LED en movimiento.

He intentado dormir/dormido, pero una vez que la duración del sueño finaliza parece que se salta el resaltado/destello todos juntos.

Por ejemplo:

- (void) button_circleBusy:(id)sender{ 
firstButton.enabled = NO; 
sleep(1); 
firstButton.enabled = YES; 

y así sucesivamente para el resto de los botones. HACE retraso, pero no retrasa el "firstButton.enabled = NO;". Tengo una imagen para el "estado desactivado" de cada botón y nunca la veo.

¡Se agradece cualquier ayuda! He investigado NSTimer pero no estaba seguro de cómo implementarlo.

Gracias.

-Paul

Respuesta

50

sleep no funciona debido a que la pantalla sólo se puede actualizar después de que sus principales declaraciones de rosca en el sistema. NSTimer es el camino a seguir. Para hacer esto, debe implementar métodos que serán llamados por el temporizador para cambiar los botones. Un ejemplo:

- (void)button_circleBusy:(id)sender { 
    firstButton.enabled = NO; 
    // 60 milliseconds is .06 seconds 
    [NSTimer scheduledTimerWithTimeInterval:.06 target:self selector:@selector(goToSecondButton:) userInfo:nil repeats:NO]; 
} 
- (void)goToSecondButton:(id)sender { 
    firstButton.enabled = YES; 
    secondButton.enabled = NO; 
    [NSTimer scheduledTimerWithTimeInterval:.06 target:self selector:@selector(goToThirdButton:) userInfo:nil repeats:NO]; 
} 
... 
+0

Hey ughoavgfhw, gracias por responder. ¡Bien, eso parece bastante fácil! Pero también tengo otra función llamada button_killAll() donde debería deshabilitar todo durante .06 segundos. Observé cómo el NSTimer utiliza el selector: @selector (goToSecondButton :), ¿qué sucede si no quiero ir a otra función y solo retrasar la desactivación durante .06 segundos? Supongo que otra manera de hacer esta pregunta es que una vez que alcanzo el último botón para resaltar/deshabilitar, ¿qué debo poner ya que no quiero que termine ese ciclo? – Retro

+0

quiere ese bucle hasta el final * – Retro

16

Trate

NSDate *future = [NSDate dateWithTimeIntervalSinceNow: 0.06 ]; 
[NSThread sleepUntilDate:future]; 
+0

Esto se puede hacer en una línea como se muestra a continuación. – Barry

25

Una forma un poco menos detallado es utilizar el performSelector: withObject: afterDelay: que establece el objeto NSTimer para usted y se puede cancelar fácilmente

Continuando con el ejemplo anterior, esto sería

[self performSelector:@selector(goToSecondButton) withObject:nil afterDelay:.06]; 

Más info in the doc

+0

Prefiero esta solución. performSelector mantiene la verbosidad al mínimo. –

0
[NSTimer scheduledTimerWithTimeInterval:.06 target:self selector:@selector(goToSecondButton:) userInfo:nil repeats:NO]; 

es el mejor para usar. Usando sueño (15); hará que el usuario no pueda realizar ninguna otra acción. Con la siguiente función, reemplazará goToSecondButton con el selector o comando apropiado, que también puede ser de los marcos.

47
int64_t delayInSeconds = 0.6; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    do something to the button(s) 
}); 
+1

+1 Me gusta esta sintaxis. Gracias. – Unheilig

+0

¡Eres increíble! Gracias, ¡he estado buscando esto por años! –

+1

¡Eso es útil! +1 y Gracias –

29

Menos código es mejor código.

[NSThread sleepForTimeInterval:0.06]; 

Swift:

Thread.sleep(forTimeInterval: 0.06) 
+0

Mucho mejor. Gracias. – Barry

+1

Solo después de que "El código legible es mejor que el código ilegible", que es un defensor aún más importante de esta respuesta. –

+0

Me encanta menos código, pero no permite que la pantalla se actualice según lo requiera el interrogador. Del documento en NSThread sleepForTimeInterval: 'No se produce ningún procesamiento de ciclo de ejecución mientras el hilo está bloqueado. – slothbear

3

me gustaría añadir un poco la respuesta por Avner Barr. Al usar int64, parece que cuando superamos el valor 1.0, la función parece retrasarse de manera diferente. Entonces creo que en este punto, deberíamos usar NSTimeInterval.

Por lo tanto, el código final es:

NSTimeInterval delayInSeconds = 0.05; 

dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 

//do your tasks here 

});