Goles
Goles

Reputation: 11799

How to know if several blocks have completed execution before taking action?

I'm using animateWithDuration:animations:completion: to move several elements of my User Interface (about 4 elements) before removeFromSuperview: is called.

My question is, how can I know that all those animations have completed before calling removeFromSuperview:?

Upvotes: 5

Views: 922

Answers (3)

Mark Pauley
Mark Pauley

Reputation: 1485

You can also use CATransaction. It will catch any embedded animations:

 [CATransaction begin];
 [CATransaction setCompletionBlock:^{ // all animations finished here }];
 [UIView animateWithDuration...
 [UIView animateWithDuration...
 ...
 [CATransaction commit];

This would allow you to not have to keep track of the animations yourself.

Upvotes: 1

Goles
Goles

Reputation: 11799

Ok, to answer my own question.

I ended up doing something like this:

    // Create dispatch queue & group
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();

    // Two group enters
    dispatch_group_enter(group);
    dispatch_group_enter(group);

    // (notice the group parameter in dispatch_group_leave)
    [UIView animateWithDuration:0.3 animations:^{
        self.pickerView.frame = CGRectMake( self.pickerView.frame.origin.x
                                           , self.view.bounds.size.height + self.pickerView.frame.size.height/2
                                           , self.pickerView.frame.size.width
                                           , self.pickerView.frame.size.height);
    } completion:^(BOOL finished){
        dispatch_group_leave(group);
    }]; 


    [UIView animateWithDuration:0.3 animations:^{
        self.navigationBar.frame = CGRectMake( self.navigationBar.frame.origin.x
                                              , -self.navigationBar.frame.size.height
                                              , self.navigationBar.frame.size.width
                                              , self.navigationBar.frame.size.height);
    } completion:^(BOOL finished){
        dispatch_group_leave(group);
    }];

    // Finishing callback
    dispatch_group_notify(group, queue, ^{
        [self.view removeFromSuperview];
    });

    // Release the group
    dispatch_release(group);

I hope this can serve as an example for someone else.

Upvotes: 9

David Hoerl
David Hoerl

Reputation: 41642

Create a dispatch queue, suspend it by the number of animations you are doing. Add a block to the queue that does the remove from superview. In the completion block of each animation resume the suspended queue. When the last one completes, the queued block will run.

Upvotes: 0

Related Questions