How can I have a handler for repeating UIView animateWithDuration?

I am using the UIView class's animateWithDuration method to repeat the animation of my view. How can I get a handler that can be used to stop this animation later? For example, a re-animation starts with one method and I need to stop it later from another method.


source to share

4 answers

You could do something like this, assuming you created an overridden property. As noted in the comments, triggering a startup completion block. The animation call needs to be wrapped in an asynchronous call to avoid. Be sure to replace "id" with whatever class type you have.

- (void)startAnimation {
    [UIView animateWithDuration:1.0
                        options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
                     animations:^(void) {
                     completion:^(BOOL finished) {
                         if(!self.canceled) {
                             __weak id weakSelf = self;
                             [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                 [weakSelf startAnimation];




The purpose of animation is to repeatedly animate the bounce of the image. When not worrying about manually stopping, you just need to set three properties (UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat)

and an animation block to move the image - = CGPointMake(,;

Here is the complete animation code:

[UIView animateWithDuration:0.5 delay:0 options:( UIViewAnimationOptionCurveEaseIn | 
 UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat | 
 UIViewAnimationOptionAllowUserInteraction) animations:^{ = 
 CGPointMake(,;} completion:nil];


What is it. But if you require manual control, then an additional code is required. First, according to jaminguy, you need to have a BOOL property to indicate the loop / stop (self.playAnimationForImage) animation, and clean up a separate method with animation code to be called from elsewhere. Here's the way:

 [UIView animateWithDuration:0.5 delay:0 options:( 
  UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAutoreverse |  
  UIViewAnimationOptionAllowUserInteraction) animations:^{ = 
  CGPointMake(,;} completion:^(BOOL finished){if 
  (finished && self.playAnimationForImage){ = CGPointMake(,; 
    [self animateImageBounce];


and here is the start of calling animation from some method

self.playAnimationForFingers = YES;
[self animateImageBounce];



What I would like to point out is that with manual control, you need to reset the center.y of the image back right before making the next recursive call.



Actually the solution with recursive call didn't work for me. The animation started to behave strangely: every 2-3 cycles of animation repetition, I got animation breaks. After the first bounce of the part (moving the object down), the second part (upward movement) performed almost instantly. I believe it has something to do with the recursive call.

So I refused to use that. The solution was to start the animation with auto-reverse and repeat options, and in a full block check if the flag ( self.playAnimationForFingers

) indicates to stop the animation.

  //fix: reset the place of bouncing fingers (starting place). 
  //Otherwise the fingers will slowly move to the bottom at every level. 
  //This resetting is not working when placed inside UIView 
  //animate complete event block = CGPointMake(10 + self.image.frame.size.width/2, 
                                  95 + self.image.frame.size.height/2); 

  [UIView animateWithDuration:0.5 delay:0 
    options:(UIViewAnimationOptionCurveEaseIn | 
             UIViewAnimationOptionAutoreverse | 
             UIViewAnimationOptionRepeat |
    animations:^{ = CGPointMake(, 
    completion:^(BOOL finished){
      /*finished not approapriate: finished will not be TRUE if animation 
      was interrupted. It is very likely to happen because animation repeats && */
      if (!self.playAnimationForFingers){
         [UIView setAnimationRepeatAutoreverses:NO]; 




U can use CABasicAnimation.

    CABasicAnimation *appDeleteShakeAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
appDeleteShakeAnimation.autoreverses = YES;
appDeleteShakeAnimation.repeatDuration = HUGE_VALF;
appDeleteShakeAnimation.duration = 0.2;
appDeleteShakeAnimation.fromValue = [NSNumber numberWithFloat:-degreeToRadian(5)];
appDeleteShakeAnimation.toValue=[NSNumber numberWithFloat:degreeToRadian(5)];
[self.layer addAnimation:appDeleteShakeAnimation forKey:@"appDeleteShakeAnimation"];


Then when u wants to stop it you can just call

[self.layer removeAnimationForKey:@"appDeleteShakeAnimation"];




All Articles