2013-02-27 11 views
7

Mam blok animacji do wykonania prostej animacji opartej na transformacji, która po zakończeniu usuwa dany widok z jego podglądu.UIView blok animacji wstrzymuje zarówno animację, jak i kod zakończenia

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

I wtedy użyć kodu jak opisano przez Tech Q & A 1673 http://developer.apple.com/library/ios/#qa/qa1673/_index.html aby wstrzymać animację.

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

Jednak ten kod nie uniemożliwia wykonania kodu ukończenia. Tak aby zapobiec kod z wykonaniem zmienić kod zakończenia do tego:

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

Podczas sprawdzania zakończeniu == TRUE zapobiega kod zakończenia od wykonywanego podczas gdy blok animacja jest wstrzymana. Jeśli czas trwania zostanie przekroczony przed "wznowieniem" animacji, kod zakończenia nie zostanie wykonany. tzn. w tym przypadku msgView pozostaje w superview.

Czy mimo to można wstrzymać/wznowić animację i zegar powiązany z kodem zakończenia (jeśli tak się dzieje)?

+1

Interesujące pytanie. Może być interpretowany jako błąd w systemie iOS. Aby obejść ten problem, sugeruję, abyś pozbył się fragmentu ukończenia animacji, a zamiast tego stwórz własny NSTimer, którego aktualnym zakończeniem jest jego inwokacja. W ten sposób możesz zatrzymać timer wewnątrz warstwy pauzy (ustawiając fireDate daleko w przyszłości). Wewnętrzna wartość wznowieniowa, którą zresetował fireDate, aby była (timeSincePause + 5.0) – Rikkles

+0

Miałem nadzieję dostać się bezpośrednio do CAMediaTiming związanej z kodem zakończenia, w taki sam sposób, w jaki robimy to z warstwą. Myślę, że byłoby to o wiele lepsze rozwiązanie. – VariableSquid

+0

Napisałem testową aplikację pod iOS 6.1 i zachowuje się ona poprawnie, tzn. Zegar transformacji zatrzymuje się. W jakim systemie OS testujesz? – Rikkles

Odpowiedz

5

Jak już powiedziałem w komentarzach powyżej, nie wydaje się, aby był problem. Poniższy test jest testowany na iOS 5.1 i 6.1.

Utwórz scenorys z UIImageView *transView i UIButton *trigger. Oto klasa:

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

Po naciśnięciu przycisku wyzwalającego, rozpoczyna się animacja. Naciśnij ponownie, animacja zostanie zatrzymana. Zaczekaj 10 sekund i jeszcze raz naciśnij przycisk. Animacja trwa i kończy się, a loguje się "Gotowe".

Powiązane problemy