2013-02-27 113 views
7

我有一個動畫塊來執行簡單的基於變換的動畫,完成時從其超級視圖中刪除有問題的視圖。UIView動畫塊會暫停動畫和完成代碼

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

我然後使用代碼作爲由Tech Q &甲1673 http://developer.apple.com/library/ios/#qa/qa1673/_index.html 詳述暫停動畫。

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

但是,這段代碼並不妨礙完成代碼的執行。因此,爲了防止執行我更改代碼完成此代碼:

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

雖然檢查結束== TRUE阻止而動畫塊暫停正在執行的完成代碼。如果在「取消暫停」動畫之前,持續時間現在已過時,則完成代碼將不會執行。即在這種情況下,msgView保留在超級視圖中。

無論如何暫停/取消暫停與完成代碼相關的動畫和定時器(如果這是怎麼回事)?

+1

有趣的問題。可以被解釋爲iOS中的錯誤。 爲了解決這個問題,我建議你擺脫動畫的完成片段,而改爲創建自己的NSTimer,並將其當前的完成作爲其調用。通過這種方式,您可以在暫停圖層中停止定時器(通過將fireDate設置在將來)。裏面resumeLayer你重置fireDate是(timeSincePause + 5.0) – Rikkles 2013-02-28 10:26:09

+0

我希望能夠直接獲得與完成代碼相關的CAMediaTiming,就像我們用層做的一樣。我認爲這將是一個更好的解決方案。 – VariableSquid 2013-02-28 11:32:18

+0

我在iOS 6.1下編寫了一個測試應用程序,它的行爲正確,即轉換的計時器暫停。你在什麼操作系統下測試? – Rikkles 2013-02-28 12:54:43

回答

5

正如我在上面的評論中所說,似乎沒有問題。以下是在iOS 5.1和6.1中測試的。

UIImageView *transViewUIButton *trigger創建故事板。下面是類:

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

當您按下觸發按鈕,動畫開始。再按一次,動畫停止。等待10秒鐘,然後再次按下按鈕。動畫繼續並完成,並記錄「完成」。