pete
pete

Reputation: 3050

IOS Animation not working with my animation block

Im Trying to make a red square move from top of view to a random position at the bottom of the view and the return to the top again at random position. The app starts with the following code into [super viewLoad]:

[redSquare setCenter:CGPointMake(25,25)];

(with the red square view set 50 x 50, this starts the app with the redsquare in the top left corner).

The first part of the animation works well - the red square animates to a random position to the bottom of the page. But, it then jumps to a random position to the top without animation. Please help what I'm doing wrong or any other solutions to help with this simple animation.

 -(void)moving{

    [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationCurveEaseIn animations:^{
   int randomx = arc4random() % 295;
   [redSquare setCenter:CGPointMake(randomx,435)];


    } completion:^(BOOL finished) {

   [redSquare setCenter:CGPointMake(redSquare.frame.origin.x,25)];
   }];

}

Upvotes: 3

Views: 2150

Answers (3)

Abizern
Abizern

Reputation: 150615

Your completion block simply sets the new position. You aren't animating it back to the top:

Try this, instead

-(void)moving {

    [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationCurveEaseIn animations:^{
        int randomx = arc4random() % 295;
        [redSquare setCenter:CGPointMake(randomx,435)];
    } completion:^(BOOL finished) {
        [UIViewAnimateWithDuration:1.0 delay:0.0 options:UIViewAnimationCurveEaseIn animations:^{
        [redSquare setCenter:CGPointMake(redSquare.frame.origin.x,25)];
        } completion: NULL
    }];

}

Edited to add

It's true that sublevels can get confusing, but you can make life simple and less indented if you define the blocks separately from the method.

For example, you could rewrite the above as:

-(void)moving {

    workBlk_t animationBlock = ^ {
        int randomx = arc4random() % 295;
        [redSquare setCenter:CGPointMake(randomx,435)];
    };

    void (^completionBlock)(BOOL finished) = ^{
        [UIViewAnimateWithDuration:1.0 delay:0.0 options:UIViewAnimationCurveEaseIn animations:^{
            [redSquare setCenter:CGPointMake(redSquare.frame.origin.x,25)];
        } completion : NULL
    };

    [UIView animateWithDuration:1.0 
                          delay:0.0 
                        options:UIViewAnimationCurveEaseIn 
                     animations:animationBlock 
                     completion:completionBlock
    }];

}

Upvotes: 4

jake_hetfield
jake_hetfield

Reputation: 3398

This part does exactly what you are describing:

completion:^(BOOL finished) {
   [redSquare setCenter:CGPointMake(redSquare.frame.origin.x,25)];
}

I.e. returns the object to the top of the screen after the animiation is completed. This will not be animated, it will happen after the animation is completed, and thus it will be instant.

You need to trigger a new animation after the animation is completed.

To create several nested animation blocks can however become a bit messy, the most clean way is to create another method for animating back and call it when the first animation is completed, like this:

-(void) moveDown{
   [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationCurveEaseIn animations:^{
       int randomx = arc4random() % 295;
       [redSquare setCenter:CGPointMake(randomx,435)];

   } completion:^(BOOL finished) {
       // First animation completed
       [self moveBack];
   }];
}

-(void) moveBack{
   [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationCurveEaseIn animations:^{
       [redSquare setCenter:CGPointMake(redSquare.frame.origin.x,25)];
   } completion:^(BOOL finished) {
       // Second animation completed
   }];
}

Upvotes: 1

sheraza
sheraza

Reputation: 511

you should start new animation in completion block for example:

    completion:^(BOOL finished) {
          [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationCurveEaseIn      animations:^{
          int randomx = arc4random() % 295;
          [redSquare setCenter:CGPointMake(randomx,25)];


    } completion:^(BOOL finished) {


   }];
   }];

Upvotes: 2

Related Questions