How to call one termination block for a nested UIView group animateWithDuration?

I have a package of animated calls made by iterating through an array. All of these calls are nested in an encapsulating animation block so that they run efficiently in parallel. I also have a completion block when I only want to run as soon as all the nested animations are complete.
The problem is that the nested animations have unknown durations, so I can’t just figure out which call will be the last and finish the block ending this call. Similarly, I cannot calculate the duration and use the delayed call in the completion block.
Hope this example becomes clearer. This is a (very simplified) version of what I'm trying to do:

-(void) animateStuff:(CGFloat)animationDuration withCompletionBlock:(void) (^)(BOOL)completionBlock {

// encapsulating animation block so that all nested animations start at the same time
 [UIView animateWithDuration:animationDuration animations:^{

    for(MyObject* object in self.array) {
        // this method contains other [UIView animateWithDuration calls...
        [self animationOfUnknownDurationWithObject:object nestedCompletionBlock:^(BOOL finished) {
            // what I effectively what here is:
            if(last animation to finish) {
                completionBlock(YES);
            }
        }];
    }

 }]; // cannot use the completion block for the encapsulating animation block, as it is called straight away
}

, dispatch_groups , :
http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

, , UIView animateWithDuration , dispatch_group_async . , - __block, nestedCompletionBlock , , , , ( ).
? , - animateWithDuration , dispatch_group_async?

iOS 5.0.

UPDATE:

@Rob-
! - CATransaction, , , .:)
. , , , (.. ), .
, , :

-(void) testAnim {
NSArray* testArray = [NSArray arrayWithObjects:self.redView, self.blueView, nil];

[CATransaction begin]; {
    [CATransaction setCompletionBlock:^{
        NSLog(@"All animations complete!");
    }];

    for(UIView* view in testArray) {
        [CATransaction begin]; {

            [CATransaction setCompletionBlock:^{

                [CATransaction begin]; {
                    [CATransaction setCompletionBlock:^{
                        NSLog(@"2nd stage complete");
                    }];

                    NSLog(@"Animation 2nd stage");
                    [UIView animateWithDuration:2 animations:^{
                        setX(view, 100);
                    }];
                } [CATransaction commit];
            }];

            NSLog(@"animation 1st stage");
            [UIView animateWithDuration:2 animations:^{
                setX(view, 150);
            }];
        }[CATransaction commit];
    }

} [CATransaction commit];
}

:

2011-12-08 15: 11: 35.828 testProj [51550: f803] 1-
2011-12-08 15: 11: 35.831 testProj [51550: f803] 1-
2011-12-08 15: 11: 37.832 testProj [51550: f803] 2-
2011-12-08 15: 11: 37.834 testProj [51550: f803] 2-
2011-12-08 15: 11: 37.848 testProj [51550: f803] !
2011-12-08 15: 11: 39.834 testProj [51550: f803] 2-
2011-12-08 15: 11: 39.851 testProj [51550: f803] 2-

, " !" .
, - , , , ?
, UIView animateWithDuration , .
?

+4
2

CATransaction completionBlock. :

static void setX(UIView *view, CGFloat x)
{
    CGRect frame = view.frame;
    frame.origin.x = x;
    view.frame = frame;
}

- (IBAction)startAnimation:(id)sender {
    label.text = @"Animation starting!";
    setX(redView, 0);
    setX(blueView, 0);
    [CATransaction begin]; {
        [CATransaction setCompletionBlock:^{
            label.text = @"Animation complete!";
        }];
        [UIView animateWithDuration:1 animations:^{
            setX(redView, 300);
        }];
        [UIView animateWithDuration:2 animations:^{
            setX(blueView, 300);
        }];
    } [CATransaction commit];
}

QuartzCore, .

: , , .

, , +[UIView animateWithDuration:delay:options:animations:completion:] , .

+3

.

-(void) testAnim2 {
   // NSArray* testArray = [NSArray arrayWithObjects:self.redView, self.blueView, nil];



    [CATransaction begin]; {
        [CATransaction setCompletionBlock:^{

            [CATransaction begin]; {

                [CATransaction setCompletionBlock:^{
                    NSLog(@"All completion block");

                }];


            }[CATransaction commit];

            NSLog(@"animation 2nd stage");
            [UIView animateWithDuration:2 animations:^{
                setX(blueView, 150);
            }];


        }];
        NSLog(@"animation 1st stage");
        [UIView animateWithDuration:2 animations:^{
            setX(redView, 150);


        }];


    } [CATransaction commit];
}
+1

All Articles