Darren
Darren

Reputation: 10129

UIView animation completion block not being called

I have a strange bug that I've found in the app I'm working on. Before I get into the details I'll state my questions which are

1 - Why could a UIView animation completion block not be called

2 - Why would the UIView animation completion block then be called after a modal view is presented?

I have a series of UIView animations that begin after the view controller appears. They have completion blocks. The vast majority of the time the animation completion blocks get called. But every so often the app gets into a state where the completions blocks don't get called.

Furthermore, when I present a new view controller modally from the current view controller, the animation completion blocks that weren't called before all get called.

Once the app is in this state, the animation completion blocks never get called again, except when I present the modal view again.

My animation block is basically this:

 int i = 0;
 for (UIView *view in self.cellImageViews)
 {
     [UIView animateWithDuration:CELL_ANIMATION_DISMISS_DURATION
                           delay:(i)*CELL_ANIMATION_STAGGER_INTERVAL
                         options:UIViewAnimationOptionCurveEaseIn
                      animations:^{
                          view.transform = CGAffineTransformTranslate(view.transform, 0, CELL_ANIMATION_DISMISS_TRANSLATION);
                      } completion:^(BOOL finished) {
                         NSLog(@"Animation Completed: i:%d, finished:%d, count%d",i,finished,[self.oldCellImageViews count])
                         if(finished && (i == ([self.cellImageViews count]-1)))
                         {
                            NSLog(@"if statement passed");
                            // My completion block stuff goes here
                         } 
                       }             
         ];
        i++;
    }

Upvotes: 2

Views: 3227

Answers (2)

SwiftArchitect
SwiftArchitect

Reputation: 48514

CALayer animations are not queued but compounded. In the current approach, you are scheduling some animations to start before one or more previous ones hasn't had a chance to complete.

If you absolutely want to to queue CALayer animations, you have other options, some of which are:

  1. trigger the new animation in the completion ^block of the preceding one (chaining).
  2. use a delegate and trigger the new animation in the -animationDidStop:finished:.
  3. You may get away with UIViewAnimationOptionBeginFromCurrentState in a pinch.

The real solution is not use CALayer animations, but CAAnimation.

Upvotes: 1

Nirav Gadhiya
Nirav Gadhiya

Reputation: 6342

try following

[UIView animateWithDuration:CELL_ANIMATION_DISMISS_DURATION
                      delay:(i)*CELL_ANIMATION_STAGGER_INTERVAL
                    options:UIViewAnimationOptionCurveEaseIn
                 animations:^{
                     int i = 0;

                     for (UIView *view in self.cellImageViews)
                     {
                         view.transform = CGAffineTransformTranslate(view.transform, 0, CELL_ANIMATION_DISMISS_TRANSLATION);
                         i++;
                     }

                 } completion:^(BOOL finished) {
                     if(finished)
                     {
                         NSLog(@"if statement passed");
                         // My completion block stuff goes here
                     }
                 }
 ];

Upvotes: 1

Related Questions