20

i currently focus the following problem:

i start an animation, where 2 objects-attributes are triggered.

the code is:

    [UIView animateWithDuration:0.3 animations:^{
        greyscaleImage.alpha     = 1;
        activityIndicator.alpha  = 1;
    } completion:^(BOOL f){
        if(f)
        {
            [activityIndicator startAnimating];
        }
    }];

which works fine.

the only problem i discovered is, that i have a 0.3 seconds change to crash the app when the view which holds this activityIndicator and greyscaleImage is deallocated.

To make it more clear please imagine a ViewController, its view presented via default iOS-modal-View ways. Now trigger that animation, which takes 2 minutes. before reaching that 2 minutes, you find that animation is quite boring and you want to dismiss that view. now, that the view, activityIndicator and greyscaleImage are released, the animation o/c cannot know what to do.

so i wonder, what to do here + why the debugger points to

  } completion:^(BOOL f){

instead of e.g. [activityIndicator ...

is there a way, to allow user to dismiss the view before the 2 minutes are over?

Best Regards

thedanielhanke
  • 730
  • 1
  • 6
  • 22
  • 1
    possible duplicate of [How to cancel UIView block-based animation?](http://stackoverflow.com/questions/9569943/how-to-cancel-uiview-block-based-animation) – Vladimir Dec 04 '13 at 09:05

4 Answers4

32

If you start a new animation that takes 0.0 seconds and goes to the state you want to go to, it will cancel the old one and start the new (instant) 'animation'.

Example for when you want to stop a moving view by going to the place it already is at:

[UIView animateWithDuration:0.0
                      delay:0.0
                    options:UIViewAnimationOptionBeginFromCurrentState
                 animations:^{movingView.frame = ((CALayer *)movingView.layer.presentationLayer).frame;}
                 completion:^(BOOL finished){}
 ];

options:UIViewAnimationOptionBeginFromCurrentState is important. Not calling it will let your animation start at the end state of the previous animation. In movement, it would warp to the end location before warping to the place you want it to stop at. Even though your cancel-'animation' is instant, the jumping back and forth may be visible.

Note: The animation time doesn't have to be 0.0 seconds, any animation will cancel the old one. Not entirely sure about different types of animations though. For example, I don't know if changing a frame would stop a fade.

Aberrant
  • 3,423
  • 1
  • 27
  • 38
  • thank you! i just noticed, that setting one of the changed properties also canceled the block execution. thanks a lot. – thedanielhanke Nov 01 '11 at 14:32
  • Note that for me "setting one of the changed properties" didn't "cancel the block execution" (which doesn't make sense because the block execution cannot be cancelled) and neither cancelled the ongoing animations. – Ricardo Sanchez-Saez Apr 15 '13 at 14:05
7

You can remove all the animations from the views layer

[movingView.layer removeAllAnimations];
Chris
  • 2,727
  • 2
  • 27
  • 28
  • 2
    @Ninja - removeAllAnimations has not been removed from the API so it should work https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CALayer_class/index.html – Chris Mar 31 '15 at 06:50
  • does not work for me. It still wait for the previous animation duration before starting. – Dan Aug 12 '15 at 00:00
1

Setting animation options UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction work for me.

Use it like this:

[UIView animateWithDuration:0.5
                          delay:0.0
         usingSpringWithDamping:0.7
          initialSpringVelocity:0
                        options:UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction
                     animations:^{
                    // Do your stuff here, like changing the frame etc.
                    self.containerView.frame = CGRectMake(0, 100, 300, 300);
    } completion:nil];
atulkhatri
  • 10,896
  • 3
  • 53
  • 89
1

Blocks will always complete after they start, and cannot be stopped (unless you crash the app). You might want to use notification center or NSTimer to manually change frames instead.

  • You could also set a flag to check, but there would be a 0.3 second delay until the block completes. –  Nov 01 '11 at 13:52