2011-11-06 7 views
5

Ho un menu con elementi che appaiono subito dopo l'altro in intervalli di 3 secondi, lo sto facendo in questo modo:Fermare tutte le animazioni in corso di esecuzione su diversi filo

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]; 
    }        
} 

è possibile interrompere l'animazione nel mezzo (quando un pulsante viene toccato, ad esempio)? Ho provato a impostare tutto su alpha 1.0 ma, come previsto, i thread continuavano a funzionare e mostra di nuovo gli elementi.

Apprezzerebbero qualsiasi idea :)
Shai.

+0

Non correlato alla domanda, ma il thread UIKit è al sicuro? – Rog

+0

Non so davvero cosa significhi:> –

+0

A meno che le cose non siano cambiate su iOS5 (e non credo che lo siano), si suppone che tu debba aggiornare la tua interfaccia utente tramite il thread principale. Le code di invio stanno aggiornando l'interfaccia utente su un thread in background e questo potrebbe causare problemi di instabilità con la tua app. Ecco qualcosa dalla documentazione ufficiale (parte inferiore della pagina) http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKit_Framework/Introduction/Introduction.html#//apple_ref/doc/uid/TP40006955 -CH1-SW1 – Rog

risposta

3

Si potrebbe fare le animazioni usando UIView animazioni block-based, con il set delay:. Nessun problema sul filo.

Queste animazioni possono essere interrotte avviando un'altra animazione basata su blocchi con l'opzione UIViewAnimationOptionBeginFromCurrentState impostata.

Per transizioni alfa questo va bene poiché non importa quale sia la posizione corrente dell'animazione. Se si spostano oggetti, è possibile ottenere la posizione corrente interrogando lo view.layer.presentationLayer che contiene lo stato corrente dell'oggetto. Per eseguire questa operazione è necessario importare il framework QuartzCore. Questo ti dà anche un metodo, removeAllAnimations che farà praticamente quello che sembra e porta qualsiasi vista direttamente al punto finale di eventuali animazioni in attesa o attive.

+0

Il problema non sto solo suonando l'alfa, sto anche suonando un suono con CocoDenshion. Proverò il tuo metodo e vedrò se funziona. Grazie man :) –

+0

il seguente codice mostra tutti gli elementi contemporaneamente con i ritardi, per qualche motivo: http://pastebin.com/dVEzCEWr –

+0

Il blocco di completamento non viene eseguito fino alla fine dell'animazione. Incrementa i nel tuo ciclo for, prima che ogni animazione sia impostata. Stavo per aggiungere che potresti suonare il tuo suono nel blocco di completamento, se l'animazione è interrotta il parametro BOOL sarà NO, quindi non sai suonare il suono. – jrturton

0

Forse troverai risposta nella risposta this e forse farai la tua roba in altro modo.

+0

Questo commento mi dice principalmente che l'approccio di dispatch_async non è il modo giusto, non fornisce realmente un'alternativa a meno che non stiamo parlando di [NSThread performSelector], e anche allora, non avrei una risposta alla mia domanda sopra (fermandosi animazioni già programmate). –

+1

Inoltre, anche se apprezzo il tuo tempo - non penso che una frase e un link siano considerati una risposta. Dovrebbe essere un commento la prossima volta. Ancora una volta, grazie per il tuo tempo a prescindere. –

+0

Nessun problema. Trovo questo fondamentale codice sorgente della categoria NSObject per blocchi ritardati e cancellati https://gist.github.com/955123 Se userete questi metodi per creare istanze di blocchi e provate a salvarli, allora potete chiamare cancelBlock: metodo per cancellarli . –

1

Non penso che tu possa fermare le animazioni già programmate. Ma è possibile impostare una variabile di istanza con un flag BOOL che indica se un pulsante era già stato premuto o meno.

Ad esempio, supponendo che il target del pulsante sia il metodo buttonTapped.

Inizializza flag a NO.

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

    return self; 
} 

Nel obiettivi del pulsante SET la bandiera a YES.

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

e modificare solo il alpha se la bandiera è 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; 
     } 
    }); 
} 

Si ricorda che l'invio di messaggi a UIKit, dovrebbe sempre essere fatto sul thread principale.

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

Lo sto già facendo, ma non è di grande aiuto. Sto visualizzando 6 voci di menu una alla volta, e quando l'utente fa clic su una di esse, voglio interrompere l'animazione della voce e visualizzarle tutte e annullare le animazioni nella coda –

+0

+1 per la punta del filo principale , non lo sapevo (dispatch_async in dispatch_after). Grazie uomo :) –

Problemi correlati