2013-02-27 10 views
7

Ho un blocco di animazione per eseguire una semplice animazione basata su trasformazione, che al termine rimuove la vista in questione dalla sua superview.Il blocco di animazione UIView interrompe sia l'animazione che il codice di completamento

UIView *msgView = [[UIView alloc] initWithFrame:CGRectMake(160, 120, 160, 100)]; 

// Do stuff to set up the subviews of msgView. 

// Add the msgView to the superview (ViewController) that is going to display it. 

CATransform3D transform = CATransform3DMakeScale(2.5, 2.5, 1.0); 

[UIView animateWithDuration:5.0 
       animations:^(void){msgView.layer.transform = transform;} 
       completion:^(BOOL finished){[msgView removeFromSuperview];}]; 

ho quindi usare il codice come descritto da Tech Q & A 1.673 http://developer.apple.com/library/ios/#qa/qa1673/_index.html sospendere l'animazione.

-(void)pauseLayer:(CALayer*)layer 
{ 
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; 
    layer.speed = 0.0; 
    layer.timeOffset = pausedTime; 
} 

-(void)resumeLayer:(CALayer*)layer 
{ 
    CFTimeInterval pausedTime = [layer timeOffset]; 
    layer.speed = 1.0; 
    layer.timeOffset = 0.0; 
    layer.beginTime = 0.0; 
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; 
    layer.beginTime = timeSincePause; 
} 

Tuttavia, questo codice non impedisce l'esecuzione del codice di completamento. Quindi, per evitare che il codice da eseguire a cambiare il codice per il completamento di questo:

completion:^(BOOL finished){if(finished == TRUE)[msgView removeFromSuperview];}; 

Mentre controllando finito == TRUE impedisce il codice di completamento venga eseguito mentre il blocco animazione è in pausa. Se la durata è stata cancellata prima di "annullare la pausa" dell'animazione, il codice di completamento non verrà eseguito. cioè In questo caso il msgView rimane nella superview.

Esiste comunque la possibilità di sospendere/riattivare sia l'animazione che il timer associati al codice di completamento (se è ciò che sta succedendo)?

+1

Interessante domanda. Potrebbe essere interpretato come un bug in iOS. Per ovviare a questo problema, ti suggerisco di liberarti del pezzo di completamento dell'animazione, e invece di creare il tuo NSTimer con il tuo completamento attuale come invocazione. In questo modo puoi fermare il tuo timer all'interno del livello di pausa (impostando il fireDate molto in futuro). All'interno resumeLayer hai resettato fireDate come (timeSincePause + 5.0) – Rikkles

+0

Speravo di ottenere direttamente il CAMediaTiming associato al codice di completamento, nello stesso modo in cui lo facciamo con il livello. Penso che sarebbe una soluzione molto migliore. – VariableSquid

+0

Ho scritto un'app di test in iOS 6.1 e si sta comportando correttamente, cioè le pause del timer della trasformazione. Quale sistema operativo stai testando sotto? – Rikkles

risposta

5

Come ho detto nei commenti sopra, non sembra esserci un problema. Il sotto è testato in iOS 5.1 e 6.1.

Creare uno storyboard con UIImageView *transView e UIButton *trigger. Ecco la classe:

TSTViewController.h:

@property (weak, nonatomic) IBOutlet UIImageView *transView; 
@property (weak, nonatomic) IBOutlet UIButton *trigger; 
@property (nonatomic) NSUInteger bState; 

- (IBAction)didPressTrigger:(id)sender; 

TSTViewController.m:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.bState = 0; // 0 is initial state 
         // 1 is transform being animated 
         // 2 is transform paused 
         // 3 is transform ended 
} 

- (IBAction)didPressTrigger:(id)sender { 
    switch (self.bState) { 
     case 0: 
     { 
      CATransform3D transform = CATransform3DMakeScale(2.5, 2.5, 1.0); 
      self.bState++; 
      [UIView animateWithDuration:5.0 
          animations:^(void){self.transView.layer.transform = transform;} 
          completion:^(BOOL finished){ 
           self.bState = 3; 
           NSLog(@"Done"); 
          }]; 
      break; 
     } 
     case 1: 
     { 
      self.bState++; 
      [self pauseLayer:self.transView.layer]; 
      break; 
     } 
     case 2: 
     { 
      self.bState = 1; 
      [self resumeLayer:self.transView.layer]; 
      break; 
     } 
     case 3: 
     { 
      [UIView animateWithDuration:0 animations:^(void){self.transView.layer.transform = CATransform3DIdentity;} 
          completion:^(BOOL finished) { 
           self.bState = 0; 
           NSLog(@"Reset"); 
          }]; 
      break; 
     } 
     default: 
      break; 
    } 
} 

-(void)pauseLayer:(CALayer*)layer 
{ 
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; 
    layer.speed = 0.0; 
    layer.timeOffset = pausedTime; 
} 

-(void)resumeLayer:(CALayer*)layer 
{ 
    CFTimeInterval pausedTime = [layer timeOffset]; 
    layer.speed = 1.0; 
    layer.timeOffset = 0.0; 
    layer.beginTime = 0.0; 
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; 
    layer.beginTime = timeSincePause; 
} 

Quando si preme il pulsante di avvio, inizia l'animazione. Premerlo di nuovo, l'animazione si interrompe. Attendere 10 secondi e premere nuovamente il pulsante. L'animazione continua e finisce e registra "Fatto".

Problemi correlati