2011-11-06 9 views
5

Tengo un menú con elementos que hacen estallar justo después de unos a otros en intervalos de 3 segundos, lo estoy haciendo de este modo:Detener todas las animaciones que se realiza en diferentes hilo

for(UIButton *menuItem in menuItems){ 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (0.3 * i) * NSEC_PER_SEC), dispatch_get_current_queue(), ^{ 
     [menuItem setAlpha:1.0]; 
    }        
} 

¿Es posible detener la animación en el medio (cuando se toca un botón, por ejemplo)? Intenté simplemente configurar todo a alpha 1.0 pero, como era de esperar, los hilos continuaron ejecutándose y muestran los elementos nuevamente.

Agradecería cualquier idea :)
Shai.

+0

No relacionado con tu pregunta, pero, ¿está UIKit seguro ahora? – Rog

+0

Realmente no sé lo que eso significa:> –

+0

A menos que las cosas hayan cambiado en iOS5 (y no creo que lo hayan hecho), solo se supone que debes actualizar tu UI a través del hilo principal. Sus colas de envío están actualizando la interfaz de usuario en una cadena de fondo y es probable que esto cause problemas de inestabilidad con su aplicación. Aquí hay algo de la documentación oficial (al final de la página) http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKit_Framework/Introduction/Introduction.html#//apple_ref/doc/uid/TP40006955 -CH1-SW1 – Rog

Respuesta

3

Usted podría hacer las animaciones usando UIView animaciones basadas en bloques, con el conjunto delay:. Ningún hilo se preocupa allí.

Estas animaciones se pueden interrumpir iniciando otra animación basada en bloques con la opción UIViewAnimationOptionBeginFromCurrentState establecida.

Para las transiciones alfa esto está bien ya que no importa cuál es la posición actual de la animación. Si está moviendo objetos, puede obtener la posición actual consultando el view.layer.presentationLayer que contiene el estado actual del objeto. Deberá importar el marco QuartzCore para hacer esto. Esto también le ofrece un método, removeAllAnimations, que hará más o menos lo que parece y lleva cualquier punto de vista al punto final de cualquier animación que tenga pendiente o activa.

+0

El problema no solo estoy jugando el alfa, también estoy jugando un sonido con CocoDenshion. Probaré tu método y veré si funciona. Thanks man :) –

+0

el siguiente código muestra todos los elementos al mismo tiempo en lugar de retrasos, por alguna razón: http://pastebin.com/dVEzCEWr –

+0

El bloque de finalización no se ejecuta hasta el final de la animación. Incrementa i en tu bucle for, antes de configurar cada animación. Estaba a punto de añadir que podría reproducir su sonido en el bloque de finalización, si la animación se interrumpe, el parámetro BOOL será NO, por lo que no sabrá reproducir el sonido. – jrturton

0

Tal vez encuentres respuesta en this respuesta y quizás harás tus cosas de otra manera.

+0

Este comentario principalmente me dice que el enfoque dispatch_async no es el correcto, realmente no ofrece una alternativa a menos que hablemos de [NSThread performSelector], e incluso entonces, no tendría una respuesta a mi pregunta anterior (detener animaciones ya programadas). –

+1

Además, aunque aprecio tu tiempo, no creo que una oración y un enlace se consideren una respuesta. Debería ser un comentario la próxima vez. De nuevo, gracias por su tiempo, independientemente. –

+0

No hay problema. Encuentro este código fuente fundamental de la categoría NSObject para bloques demorados y cancelados https://gist.github.com/955123 Si va a usar esos métodos para crear instancias de bloques e intente guardarlos, entonces puede llamar al método cancelBlock: para cancelarlos . –

1

No creo que pueda detener animaciones ya programadas. Pero podría establecer una variable de instancia con un indicador BOOL que indica si un botón ya se presionó o no.

Por ejemplo, suponiendo que los objetivos de su botón es el método buttonTapped.

Inicialice su marca en NO.

- (id)init { 
    if (self = [super init]) { 
     buttonAlreadyTapped = NO; 
    } 

    return self; 
} 

En los objetivos de su botón configurado el indicador para YES.

- (void)buttonTapped { 
    self.buttonAlreadyTapped = YES; 
} 

Y sólo modificar el alpha si la bandera es NO.

for (NSInteger i = 1; i <= [menuItems count]; i++) {   
    UIButton *menuItem = [menuItems objectAtIndex:i-1]; 

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (3 * i) * NSEC_PER_SEC), dispatch_get_current_queue(), ^{ 
     if (!self.buttonAlreadyTapped) { 
      menuItem.alpha = 1.0f; 
     } 
    }); 
} 

Recuerde que el envío de mensajes a UIKit, debe siempre así en el hilo principal.

for (NSInteger i = 1; i <= [menuItems count]; i++) {   
    UIButton *menuItem = [menuItems objectAtIndex:i-1]; 

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (3 * i) * NSEC_PER_SEC), dispatch_get_current_queue(), ^{ 
     if (!self.buttonAlreadyTapped) { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       menuItem.alpha = 1.0f; 
      }); 
     } 
    }); 
} 
+0

Ya lo estoy haciendo, pero realmente no ayuda. Estoy mostrando 6 elementos de menú uno por uno, y cuando el usuario hace clic en uno de ellos, quiero detener la animación de entrada y mostrarlos todos, y cancelar las animaciones en la cola –

+0

+1 para el consejo principal , no lo sabía (dispatch_async en dispatch_after). Gracias hombre :) –

Cuestiones relacionadas