dandan
dandan

Reputation: 509

My animatewithduration, completion block is performed only once

I use the following block of code to slide a UIView down and when finished rotate another UIView. The second part of the animation, the completion block is only performed once which means the 1st animation is not completed else it would reach the completion block. On the iphone simulator it looks as if the 1st animation did finish... can anyone help me figure this out? my NSLog says:

finished 1st

started 2nd

finished 1st

finished 1st

finished 1st
.
.
.

- (IBAction) move 
{ 
[UIView animateWithDuration:0.7 animations:^{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.7];
    [UIView setAnimationRepeatCount:1];
    [UIView setAnimationRepeatAutoreverses:NO];

    CGPoint pos = movingtTable.center;
    float moveDistance = 220.0;
    if(!isViewVisible){
        //expose the view
        pos.y = pos.y+moveDistance;
        //disable selection for xy table
        xTable.userInteractionEnabled = NO;
        yTable.userInteractionEnabled = NO;
        //angle = M_PI;
    }
    else
    {
        pos.y = pos.y-moveDistance;
        xTable.userInteractionEnabled = YES;
        yTable.userInteractionEnabled = YES;
        //angle = -M_PI;
    }
    isViewVisible = !isViewVisible;
    movingtTable.center = pos;      
    NSLog(@"finished 1st");


}completion:^(BOOL finished){
    NSLog(@"started 2nd");
        [UIView animateWithDuration:0.4 animations:^{
            //[UIView beginAnimations:nil context:NULL];
            [UIView setAnimationDuration:0.4];
            //[UIView setAnimationRepeatCount:1];
            //[UIView setAnimationRepeatAutoreverses:NO];
            arrows.transform = CGAffineTransformMakeRotation(angle); 
         }completion:^(BOOL finished){
             angle = -angle;
         }];
}];

Upvotes: 4

Views: 13152

Answers (2)

MobileVet
MobileVet

Reputation: 2958

You are mixing and matching paradigms and I believe that is causing the issue you are seeing. You are creating an animation block, but inside of that block you are creating a new animation routine with the 'old' paradigm for running UIView animations. Apple is leading people away from the old paradigm and I would encourage you to ONLY use blocks as well.

This is why the completion block only runs once, the UIView animateWith block code only runs once. However, your internal animation code runs multiple times.

Take out:

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.7];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationRepeatAutoreverses:NO];

If you want your animation block to run several times, then use the full method:

  • animateWithDuration:delay:options:animations:completion:

Make the delay = 0, and set your options to UIViewAnimationOptionRepeat, or whatever you need to accomplish the number of cycles you want the block to complete.

Here is my suggestion assuming you want it to repeat:

- (IBAction) move 
{ 
[UIView animateWithDuration:0.7 
                      delay:0 
                    options:UIViewAnimationOptionRepeat 
                 animations:^{
                               CGPoint pos = movingtTable.center;
                               float moveDistance = 220.0;

                               if(!isViewVisible) {
                                 //expose the view
                                 pos.y = pos.y+moveDistance;
                                 //disable selection for xy table
                                 xTable.userInteractionEnabled = NO;
                                 yTable.userInteractionEnabled = NO;
                                 //angle = M_PI;
                               }
                               else {
                                 pos.y = pos.y-moveDistance;
                                 xTable.userInteractionEnabled = YES;
                                 yTable.userInteractionEnabled = YES;
                                 //angle = -M_PI;
                               }
                               isViewVisible = !isViewVisible;
                               movingtTable.center = pos;      
                               NSLog(@"finished 1st");
                             }
                completion:^(BOOL finished){
                               NSLog(@"started 2nd");
                               [UIView animateWithDuration:0.4 
                                                animations:^{
                                                               arrows.transform = CGAffineTransformMakeRotation(angle); 
                                                            }
                                                completion:^(BOOL finished){
                                                               angle = -angle;
                                                            }];
                             }];
}

Upvotes: 2

serb
serb

Reputation: 318

Why are you trying to initialize another UIView animation inside the animateWithDuration block code? Update your code to the following and make sure you're not performing multiple animations of a single view at a time.

- (IBAction) move 
{ 
[UIView animateWithDuration:0.7 animations:^{
    CGPoint pos = movingtTable.center;
    float moveDistance = 220.0;
    if(!isViewVisible){
        //expose the view
        pos.y = pos.y+moveDistance;
        //disable selection for xy table
        xTable.userInteractionEnabled = NO;
        yTable.userInteractionEnabled = NO;
        //angle = M_PI;
    }
    else
    {
        pos.y = pos.y-moveDistance;
        xTable.userInteractionEnabled = YES;
        yTable.userInteractionEnabled = YES;
        //angle = -M_PI;
    }
    isViewVisible = !isViewVisible;
    movingtTable.center = pos;      
    NSLog(@"finished 1st");
}
completion:^(BOOL finished){
    NSLog(@"started 2nd");
        [UIView animateWithDuration:0.4 animations:^{
            arrows.transform = CGAffineTransformMakeRotation(angle); 
         }completion:^(BOOL finished){
             angle = -angle;
         }];
}];

BTW: The block code requires some serious refactoring, if you ask me :)

Upvotes: 2

Related Questions