0

I am doing a very simple repeating animation to fade a label in and out, seen below. I assumed the completion block would be called every time the animation finishes, but when using UIViewAnimationOptionRepeat it is never called. So how am I supposed to stop this animation?

I know I can use [self.lbl.layer removeAllAnimations];, however that ends its very abruptly. I want to know when it has finished a cycle of the animation so I can stop it at that time.

[UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveEaseInOut animations:^{
            self.lbl.alpha = 0;

        } completion:^(BOOL finished){
            if (finished) NSLog(@"done");

        }];
halfer
  • 19,824
  • 17
  • 99
  • 186
Josh Kahane
  • 16,765
  • 45
  • 140
  • 253
  • Possibly a duplicate of your earlier question http://stackoverflow.com/questions/14648913/stop-repeating-uiview-animation-block ? – jrturton Oct 20 '13 at 16:57
  • I see your thinking but its not quite the same situation. This time I am using `UIViewAnimationOptionRepeat` which changes the functionality of the animation block. `removeAllAnimations` is also a very harsh way of ending an animation when it could be at any state. – Josh Kahane Oct 20 '13 at 17:02

3 Answers3

3

If you want the animation with the UIViewAnimationOptionRepeat option to be finite, you have to set the repeat count via + (void)setAnimationRepeatCount:(float)repeatCount of UIView.

In case of block-based animation (that is your case), you should set repeat count from within animation block. So, here is your code modified:

[UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveEaseInOut animations:^{
        [UIView setAnimationRepeatCount:4]; // 4 as example here
        self.lbl.alpha = 0;

    } completion:^(BOOL finished){
        if (finished) NSLog(@"done");

    }];

This is mentioned in documentation of setAnimationRepeatCount: method of UIView.

Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119
1

maybe this kind of solution using a selector can help you:

- (void) animateTextWithMax:(NSNumber *)max current:(NSNumber *)current
{
    NSLog(@"max = %d, current = %d",max.intValue, current.intValue);
    textlabel.alpha = 1.0f;
    [UIView animateWithDuration:1.0f delay:0 options:UIViewAnimationOptionAutoreverse
                     animations:^{
                         textlabel.alpha = 0.0f;
                     }completion:^(BOOL finished){
                         NSLog(@"finished");
                         if (current.intValue < max.intValue) {
                             [self performSelector:@selector(animateTextWithMax:current:) withObject:max withObject:[NSNumber numberWithInteger:(current.intValue+1)]];
                         }

                     }];
}

then you can call the animation by this way:

[self animateTextWithMax:[NSNumber numberWithInt:3] current:[NSNumber numberWithInt:0]];

Maybe this is not the best solution because you are not using the UIViewAnimationOptionRepeat option, but I think it can work.

I hope this helps you.

vgarzom
  • 153
  • 10
0

As you've discovered, the completion block is not called, because the animation never ends. Off the top of my head, you've got two options:

  • Add another animation to the label, setting it to your desired final value, with the UIViewAnimationOptionBeginFromCurrentState option. I'm not sure what effect this has on the existing, repeating animation, though. If that doesn't work...
  • Get the current position of your animation by examining the label.layer.presentationLayer. Stop all animations, set your value to the current state, then add a new animation to transition from the current state to the desired final state.
jrturton
  • 118,105
  • 32
  • 252
  • 268