Chaining UIView animations with blocks

I really love UIView animations. They are so simple and elegant. This little chain I will make will fade in a UIView (or descendant) from the left, wait a moment, then fade out to the left. In general you can animate all of these properties: frame,bounds,center,transform,alpha,backgroundColor,and contentStretch in a UIView animation block.

For this example I created a single view application and put a UIImageView in the middle of the screen. UIImageView is a direct descendant of UIView so it is perfect for this exercise.
UIImageView

I tossed a postcard of Portland and set up an outlet and connected it, I add this code to viewDidLoad:

    CGRect middleFrame = postcardView.frame;
 
    CGRect startFrame = middleFrame;
    startFrame.origin.x = middleFrame.origin.x-120;
 
    CGRect endFrame = postcardView.frame;
    endFrame.origin.x = middleFrame.origin.x+120;
 
    //starting values
	postcardView.frame = startFrame;
	postcardView.hidden = NO;
	postcardView.alpha = 0.0f;

Basically we’ve got three different positions, the current position, which we’ll call middleFrame and also where the image will pause for a moment before fading out again. Then we’ve got startFrame and endFrame which will be to the left and right 120 points. We also set the beginning values for our UIImageView. It will start at startFrame and it will be initially hidden.

We’re going to use two different UIView methods:

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion

They are very similar with the latter adding options for a delay previous to the animation and also UIViewAnimationOptions, which are incredibly powerful.

Ok, here’s the code. We only chain two animations, but you could copy and paste in another at the completion stage, it will just add another }]; in the last line.

The first animation will take .9 seconds. It will fade in our postcard to 100% opacity (which also sets the ‘hidden’ property). It will also tween our postcard to our new location at middleFrame.

The second animation which runs on completion of the first delays itself a half second, fades out and moves to our endFrame.

On cleanup I re-hid the uiimageview and moved it back to its original location (helpful if this is to be performed multiple times).

[UIView animateWithDuration:0.9f
                     animations:^{
                         // STEP 1: FADE IN
                         [postcardView setAlpha:1.0f];
                         postcardView.frame = middleFrame;
                     }
                     completion:^(BOOL finished){
                         [UIView animateWithDuration:1.2f
                                               delay:0.5 options:UIViewAnimationOptionTransitionNone
                                          animations:^{
                                              // STEP 2: WAIT THEN FADE OUT
                                              [postcardView setAlpha:0.0f];
                                              postcardView.frame = endFrame;
                                          }
                                          completion:^(BOOL finished){
                                              // STEP 3: CLEAN UP
                                              postcardView.hidden=YES;
                                              postcardView.frame = middleFrame;
                                          }]; }];